1

I am trying to make a script which will use ffmpeg to record the screen and audio. The user will be able to choose what will be recorded: only screen, only microphone, only speakers sound or combinations of those.

I am struggling to make sound recording work. I initially tried with Alsa, but then I could hear nothing while it was being recorded. Then I tried with Pulseaudio, but the result was bad. Now I tried with OpenAL and the result is pretty good. However, its options have spaces, and I can't make the script work reliably:

The OpenAL options are:

[openal @ 0x55c6aa3b77a0] List of OpenAL capture devices on this system:
[openal @ 0x55c6aa3b77a0]   Áudio interno Estéreo analógico
[openal @ 0x55c6aa3b77a0]   Monitor of Áudio interno Estéreo analógico

The command line have different variables, depending of the user options and screen size, being:

env PULSE_LATENCY_MSEC=5 ffmpeg -vsync passthrough \
-vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi \
${monitorsom} "${openal}" ${micro} "${microal}" ${complexo}   \
-thread_queue_size 4096 -framerate 30  \
-f x11grab -s "$(xdpyinfo  | grep -oP 'dimensions:\s+\K\S+')" -i :0.0  \
-acodec libfdk_aac -b:a 192k \
-vf 'format=nv12,hwupload' -vcodec h264_vaapi \
-f flv "${nome}"

The big problem with this approach is that the variables monitorsom, openal, micro, microal and complexo can be empty. There is no problem with monitorsom, micro and complexo, the resulting command is fine. However, if openal or microal are empty, the ffmpeg command fails. If no options are chosen (no sound) the command passed is:

 env PULSE_LATENCY_MSEC=5 ffmpeg -vsync passthrough -vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi '' '' -thread_queue_size 4096 -framerate 30 -f x11grab -s 1366x768 -i :0.0 -acodec libfdk_aac -b:a 192k -vf format=nv12,hwupload -vcodec h264_vaapi -f flv TEST002.flv

It has the quotes which have to be used when there is a option, but as they are empty, the command fails.

If I try a different approach, changing the variable parts to (without any quotes):

${monitorsom} ${openal} ${micro} ${microal} ${complexo}   \

It works when they are empty, but fails when there is a option due to the spaces. I tried the following approach to pass the variable with the needed quotes:

openal=' "Monitor of Áudio interno Estéreo analógico" '

Single quotes are added in the middle of the variable value, resulting in:

'"Monitor' of Áudio interno Estéreo 'analógico"'

Consequently, failing.

If I try using:

openal="  'Monitor of Áudio interno Estéreo analógico' " 

It results in:

''\''Monitor' of Áudio interno Estéreo 'analógico'\'''

Failing.

Is there a way to pass the variable with the needed quotes? I would like to pass:

"Monitor of Áudio interno Estéreo analógico"

or

'Monitor of Áudio interno Estéreo analógico'

But it has to accept values without any quotes too. So I believe I should be able to set the variable values with quotes when quotes are needed and no quotes if they are not needed or will cause errors.

Thank you.

2

If the problem is empty arguments causing problems, consider building the command line using arrays, so that you can filter out empty variables:

opts=()
add_opt() {
    for i; do [[ -n "$i" ]] && ops+=("$i"); done
}
add_opt "${monitorsom}" "${openal}" "${micro}" "${microal}" "${complexo}"

Then:

env PULSE_LATENCY_MSEC=5 ffmpeg -vsync passthrough \
-vaapi_device /dev/dri/renderD128 -hwaccel vaapi -hwaccel_output_format vaapi \
"${opts[@]}"   \
-thread_queue_size 4096 -framerate 30  \
-f x11grab -s "$(xdpyinfo  | grep -oP 'dimensions:\s+\K\S+')" -i :0.0  \
-acodec libfdk_aac -b:a 192k \
-vf 'format=nv12,hwupload' -vcodec h264_vaapi \
-f flv "${nome}"

If an opts is empty, "${opts[@]}" expands into nothing, and we have already filtered out the empty variables.

(I'd go ahead and put every option in the array. When I have very long command lines, I tend do:

opts=(
"opt1"
"opt2"
...
)
cmd "${opts[@]}"

Which makes it easier to keep track of options for me.)

  • I had to make changes to the array creation. I was able to use successfuly the following: opts=() add_opt() { for i; do [[ -n "$i" ]] && opts+=("$i"); done } add_opt ${monitorsom} "${openal}" ${micro} "${microal}" ${complexo} – FurretUber Jun 22 '17 at 19:35
  • With all options between quotes, the command failed. With this corrected, every word from the variables without quotes are read separately, but those can be read separately with no problems. Thank you. – FurretUber Jun 22 '17 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.