Unrecognized option 'map 0:a?' - bash

Trying to make derivatives of silent video files is failing. My understanding is adding a trailing ? to the -map option makes ffmpeg ignore that stream if it does not exist, but its not working. The full script is below.
ffmpeg -n -vsync 0 -nostdin -v info -hide_banner -stats -i "${FILE}" -movflags faststart -pix_fmt yuv420p -map 0:v -map 0:a? -c:v libx264 -vf "yadif=1,format=yuv420p" -crf "${CRFVALUE}" -preset "${PRESETSPEED}" -maxrate "${MAXRATE}"k -bufsize 1835k -c:a aac -strict -2 -b:a 384k -f mp4 "${OUTPUT}"
withouth the ? after -map 0:a it works with files containing audio streams but not with silent ones. with the ? it fails all files. from the ffmpeg documentation: "A trailing ? will allow the map_channel to be optional: if the map_channel matches no channel the map_channel will be ignored instead of failing."
why isn't it working here?

Related

Multiple sounds + watermark overlay not working with ffmpeg

I have a problem with an ffmpeg command.
I want to add the same sound several times in the final video and then add a watermark above.
When I do the full command, it doesn't work correctly because the sound is only played once (the first reference):
ffmpeg -i "assets/frame%05d.png" -i "assets/sound.mp3" -loop 1 -i
"assets/watermark.png" -filter_complex
"[1:a]adelay=1000|1000[s1];[1:a]adelay=3000|3000[s2];[s1][s2]amix=2[a];[0:v][2:v]overlay=shortest=1[outv]"
-map "[outv]" -map "[a]" -c:v libx264 -pix_fmt yuv420p -preset ultrafast -y "result.mp4"
When I don't add the watermark, it works correctly:
ffmpeg -i "assets/frame%05d.png" -i "assets/sound.mp3" -filter_complex
"[1:a]adelay=1000|1000[s1];[1:a]adelay=3000|3000[s2];[s1][s2]amix=2[a]"
-map 0:v -map "[a]" -c:v libx264 -pix_fmt yuv420p -preset ultrafast -y "result.mp4"
Try this:
ffmpeg -i "assets/frame%05d.png" \
-stream_loop -1 -i "assets/sound.mp3" \
-loop 1 -i "assets/watermark.png" \
-filter_complex "[1:a]adelay=1000|1000[s1];\
[1:a]adelay=3000|3000[s2];\
[s1][s2]amix=2[a];\
[0:v][2:v]overlay=shortest=1[outv]" \
-map "[outv]" -map "[a]" -shortest \
-c:v libx264 -pix_fmt yuv420p -preset ultrafast -y "result.mp4"
-stream_loop -1 input option loops the input infinitely and -shortest output option stops the audio when video is done.
p.s., I think an aecho filter can combine the 2nd adelay and amix filters.
I found the problem was that the different frames that make up the video were not all correctly encoded which caused the problem with the sounds.
ffmpeg can't read indexed PNG correctly.
You must therefore use this option (for those like me who use imagick):
$imagick->setOption('png:color-type', 6);
$imagick->writeImage('frame00000.png');

FFMPEG use -strict -2

Hi I've been recently using the command below
Ffmpeg -i song.mp3 -loop 1 -i image.jpg -filter_complex \
"[0:a]showfreqs=mode=line:ascale=log:fscale=log:s=1280x518[sf]; \
[0:a]showwaves=s=1280x202:mode=p2p[sw]; \
[sf][sw]vstack[fg]; \
[1:v]scale=1280:-1,crop=iw:720[bg]; \
[bg][fg]overlay=shortest=1:format=auto,format=yuv420p,drawtext=fontfile=/usr/share/fonts/TTF/Vera.ttf:fontcolor=white:x=10:y=10:text='\"Rated80s Prophets Prey\" by Comics On Film'[out]" \
-map "[out]" -map 0:a -c:v libx264 -preset fast -crf 18 -c:a libopus output.mp4
from this post Showfreqs and showwaves over background image?.
However I changed the output file to from output.mkv to output.mp4 as I would prefer to use mp4
I get the below error
[mp4 # 0x7f962b816800] opus in MP4 support is experimental, add '-strict -2' if you want to use it.
Could not write header for output file #0 (incorrect codec parameters ?): Experimental feature
Error initializing output stream 0:0 --
[libopus # 0x7f962b819800] 1 frames left in the queue on closing
The main information from that error is
opus in MP4 support is experimental, add '-strict -2' if you want to use it.
but where do I use -strict -2 within the command to make the command possible
You can add it anywhere after the last input and before the output URL.
e.g.
ffmpeg -i song.mp3 -loop 1 -i image.jpg -strict -2 -filter_complex ...
or
-map "[out]" -map 0:a -c:v libx264 -preset fast -crf 18 -c:a libopus -strict -2 output.mp4
You can also write it as -strict experimental.

Can I combine these 2 commands? (or am I fighting a losing battle?)

I'm very new to ffmpeg but so far I'm enjoying it. But I'm stuck on something. I want to combine these two commands into one, something I'm sure must be possible, but after countless hours and no luck, here I am :)
ffmpeg -y -f concat -safe 0 -protocol_whitelist "file,http,https,tcp,tls" -i "tmp.images.txt" -i "tmp.audio.mp3" -filter_complex "drawbox=y=ih-38:color=black#0.6:width=iw:height=38:t=fill, drawtext=fontfile=Assets/calibrib.ttf:text='%%~ni':fontcolor=white:fontsize=14:x=(w-tw)/2:y=(h)-24" -c:v libx264 -preset veryfast -tune stillimage -shortest -pix_fmt yuv420p "tmp.slide.mp4"
ffmpeg -loop 1 -framerate 2 -i "Assets/studio.jpg" -i tmp.slide.mp4 -filter_complex "[1]scale=879:496[inner];[0][inner]overlay=207:49:shortest=1[out]" -map "[out]" -map 1:a -c:a aac -y tmp.output.mp4
the first line creates a slideshow and places text at bottom
the second line takes the slideshow video and inserts it into a background image before outputting final video
Use
ffmpeg -y -f concat -safe 0 -protocol_whitelist "file,http,https,tcp,tls" -i "tmp.images.txt" -i "tmp.audio.mp3" -i "Assets/studio.jpg" -filter_complex "[0]drawbox=y=ih-38:color=black#0.6:width=iw:height=38:t=fill, drawtext=fontfile=Assets/calibrib.ttf:text='%%~ni':fontcolor=white:fontsize=14:x=(w-tw)/2:y=(h)-24,scale=879:496[inner];[2][inner]overlay=207:49" -c:v libx264 -preset veryfast -tune stillimage -c:a aac -shortest -pix_fmt yuv420p "tmp.slide.mp4"

FFMPEG map multiple audio input files to 1 single image file in order to create multiple video output files

I am attempting to have multiple output files in ffmpeg map to multiple inputs however instead of each input mapping to a unique output I get the first input mapping to the first video and then the next videos never get created at all, I will describe exactly what I am trying to achieve below,
I need to:
create multiple video output files
from multiple audio input files
which all use the same one common image file to create the
video
I will post my command below, any help would be greatly appreciated thanks
-y -i input1.mp3 -i input2.mp3 -f image2 -loop 1 -r 2 -i imagefile.png -shortest -c:a aac -c:v mpeg4 -crf 18 -preset veryfast -movflags faststart -map 0 output1.mp4 -map1 output2.mp4
Basic command
ffmpeg -i input1.mp3 -i input2.mp3 -loop 1 -framerate 10 -i imagefile.png -map 2:v -map 0:a -vf format=yuv420p -shortest output1.mp4 -map 2:v -map 1:a -vf format=yuv420p -shortest output2.mp4
The video is filtered and encoded once per output.
With the split filter
ffmpeg -i input1.mp3 -i input2.mp3 -loop 1 -framerate 10 -i imagefile.png -filter_complex "[2:v]format=yuv420p,split=outputs=2[v0][v1]" -map "[v0] -map 0:a -shortest -movflags +faststart output1.mp4 -map "[v1]" -map 1:a -shortest -movflags +faststart output2.mp4
The video is filtered once total, and encoded separately for each output.
Pipe
ffmpeg -y -v error -loop 1 -framerate 10 -i imagefile.png -filter_complex "[0:v]format=yuv420p[v]" -map "[v]" -c:v libx264 -f nut - | ffmpeg -y -i - -i input1.mp3 -i input2.mp3 -map 0:v -map 1:a -c:v copy -shortest -movflags +faststart output1.mp4 -map 0:v -map 2:a -c:v copy -shortest -movflags +faststart output2.mp4
The video is filtered and encoded only once and each output stream copies it.

How to concatenate and output various video bitrates and a standalone audio file?

How to concatenate and output various video bitrates and a standalone audio file in ffmpeg?
My requirement is:
I have 4 input files.
Need to stitch all 4 files into single segment.
Need output with four different video bit rates: 500k, 800k 1000k 1500k
Along with that I need to extract only audio from stitched file.
So my output will be 4 different video bitrate + 1 audio only file.
tee muxer
Most efficient method is to use the tee muxer (more examples) to avoid unnecessarily encoding the audio for each output, but it is complicated to use:
ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][aud];[v]split=4[v0][v1][v2][v3]" -map "[v0]" -b:v:0 500k -map "[v1]" -b:v:1 800k -map "[v2]" -b:v:2 1000k -map "[v3]" -b:v:3 1500k -map "[aud]" -c:v libx264 -c:a aac -f tee "[select=\'v:0,aud\':movflags=faststart]500.mp4|[select=\'v:1,aud\':movflags=faststart]800.mp4|[select=\'v:2,aud\':movflags=faststart]1000.mp4|[select=\'v:3,aud\':movflags=faststart]1500.mp4|[select=aud:movflags=faststart]audio.m4a"
This example method doesn't perform two-passes which you should do when using your old school method of manually choosing the bitrate for non-streaming outputs. See FFmpeg Wiki: H.264.
simpler but less efficient method
You can do a much less complicated command but it will be less efficient because it will separately encode the audio for each output. Possibly worth the tradeoff of less complexity.
ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a];[v]split=4[v0][v1][v2][v3];[a]asplit=4[a0][a1][a2][a3]" -map "[v0]" -map "[a0]" -b:v 500k -movflags +faststart 500.mp4 -map "[v1]" -map "[a1]" -c:v libx264 -c:a aac -b:v 800k -movflags +faststart 800.mp4 -map "[v2]" -map "[a2]" -b:v 1000k -movflags +faststart 1000.mp4 -map "[v3]" -map "[a3]" -b:v 1500k -movflags +faststart 1500.mp4
But since you're wanting to target a specific bitrate you should perform two passes:
ffmpeg -y -i 1.mp4 -i 2.mp4 -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0[v];[v]split=4[v0][v1][v2][v3]" -map "[v0]" -b:v 500k -pass 1 -passlogfile 500 -f mp4 /dev/null -map "[v1]" -c:v libx264 -c:a aac -b:v 800k -pass 1 -passlogfile 800 -f mp4 /dev/null -map "[v2]" -c:v libx264 -c:a aac -b:v 1000k -pass 1 -passlogfile 1000 -f mp4 /dev/null -map "[v3]" -c:v libx264 -c:a aac -b:v 1500k -pass 1 -passlogfile 1500 -f mp4 /dev/null
ffmpeg -y -i 1.mp4 -i 2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a];[v]split=4[v0][v1][v2][v3];[a]asplit=5[a0][a1][a2][a3][a4]" -map "[v0]" -map "[a0]" -c:v libx264 -c:a aac -b:v 500k -pass 2 -passlogfile 500 -movflags +faststart 500.mp4 -map "[v1]" -map "[a1]" -c:v libx264 -c:a aac -b:v 800k -pass 2 -passlogfile 800 -movflags +faststart 800.mp4 -map "[v2]" -map "[a2]" -c:v libx264 -c:a aac -b:v 1000k -pass 2 -passlogfile 1000 -movflags +faststart 1000.mp4 -map "[v3]" -map "[a3]" -c:v libx264 -c:a aac -b:v 1500k -pass 2 -passlogfile 1500 -movflags +faststart 1500.mp4 -map "[a4]" -movflags +faststart audio.m4a
If you're using Windows replace /dev/null with NUL in the examples above.

Resources