How can I stream an image to YouTube using FFmpeg? - linux

I have an image that changes every few seconds. How can I stream it to YouTube using FFmpeg?

ffmpeg -f image2 -loop 1 -i input.jpg -re -f lavfi -i anullsrc -vf format=yuv420p -c:v libx264 -b:v 2000k -maxrate 2000k -bufsize 4000k -g 50 -c:a aac -f flv rtmp://output
-f image2 is needed to manually select the image demuxer. Otherwise, depending on the input format, it may choose a different demuxer that does not allow arbitrary replacing of input.jpg.
Replace input.jpg atomically (such as with mv but not cp) or else it may fail.
YouTube requires audio. The anullsrc filter will generate silent audio.
See FFmpeg Wiki: YouTube Streaming.
(Optional) Use the slowest -preset that provides 25 fps (or whatever frame rate you set using the -framerate image demuxer input option).

Related

Concat mp4 videos and merge their audios to the final output

I have several videos and photos and need to merge them with the cross-dissolve effect. The algorithm is next:
Create videos from images and add silent audio to them (so they will also have a sound stream):
ffmpeg -y -f lavfi -i anullsrc -loop 1 -i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/ea5c93fd-d946-4742-b8f7-ea9ae4d43441.jpg -c:v libx264 -t 10 -pix_fmt yuv420p -vf scale=750:1280 /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/ea5c93fd-d946-4742-b8f7-ea9ae4d43441.mp4
Combine all the videos and audios into one using this command:
ffmpeg
-i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/temp_68d437c0-f5e2-4651-b07e-91533480b6ef.mp4
-i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/temp_48f3c111-610d-40c7-ac71-6ce2fbb16184.mp4
-i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/temp_1593b5d8-7e16-417d-9372-2267581cd504.mp4
-i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/temp_1ac7f6be-1b12-4e31-b904-1491cc9b9494.mp4
-i /tmp/media/import-2020-Aug-19-Wednesday-05-40-34/temp_ea5c93fd-d946-4742-b8f7-ea9ae4d43441.mp4
-filter_complex
"[0:v]trim=start=0:end=8.032,setpts=PTS-STARTPTS[clip0];
[1:v]trim=start=2:end=13.047,setpts=PTS-STARTPTS[clip1];
[2:v]trim=start=2:end=13.558,setpts=PTS-STARTPTS[clip2];
[3:v]trim=start=2:end=13.186,setpts=PTS-STARTPTS[clip3];
[4:v]trim=start=2,setpts=PTS-STARTPTS[clip4];
[0:v]trim=start=9.032:end=10.032,setpts=PTS-STARTPTS[out0];
[1:v]trim=start=14.047:end=15.047,setpts=PTS-STARTPTS[out1];
[2:v]trim=start=14.558:end=15.558,setpts=PTS-STARTPTS[out2];
[3:v]trim=start=14.186:end=15.186,setpts=PTS-STARTPTS[out3];
[1:v]trim=start=0:end=2,setpts=PTS-STARTPTS[in1];
[2:v]trim=start=0:end=2,setpts=PTS-STARTPTS[in2];
[3:v]trim=start=0:end=2,setpts=PTS-STARTPTS[in3];
[4:v]trim=start=0:end=2,setpts=PTS-STARTPTS[in4];
[in1]format=pix_fmts=yuva420p,fade=t=in:st=0:d=2:alpha=1[fadein1];
[in2]format=pix_fmts=yuva420p,fade=t=in:st=0:d=2:alpha=1[fadein2];
[in3]format=pix_fmts=yuva420p,fade=t=in:st=0:d=2:alpha=1[fadein3];
[in4]format=pix_fmts=yuva420p,fade=t=in:st=0:d=2:alpha=1[fadein4];
[out0]format=pix_fmts=yuva420p,fade=t=out:st=0:d=2:alpha=1[fadeout0];
[out1]format=pix_fmts=yuva420p,fade=t=out:st=0:d=2:alpha=1[fadeout1];
[out2]format=pix_fmts=yuva420p,fade=t=out:st=0:d=2:alpha=1[fadeout2];
[out3]format=pix_fmts=yuva420p,fade=t=out:st=0:d=2:alpha=1[fadeout3];
[fadein1]fifo[fadein1fifo];
[fadein2]fifo[fadein2fifo];
[fadein3]fifo[fadein3fifo];
[fadein4]fifo[fadein4fifo];
[fadeout0]fifo[fadeout0fifo];
[fadeout1]fifo[fadeout1fifo];
[fadeout2]fifo[fadeout2fifo];
[fadeout3]fifo[fadeout3fifo];
[fadeout0fifo][fadein1fifo]overlay[crossfade0];
[fadeout1fifo][fadein2fifo]overlay[crossfade1];
[fadeout2fifo][fadein3fifo]overlay[crossfade2];
[fadeout3fifo][fadein4fifo]overlay[crossfade3];
[clip0][crossfade0][clip1][crossfade1][clip2][crossfade2][clip3][crossfade3][clip4]concat=n=9[output];
[0:a][1:a]acrossfade=d=10:c1=tri:c2=tri[A1];
[A1][2:a]acrossfade=d=10:c1=tri:c2=tri[A2];
[A2][3:a]acrossfade=d=10:c1=tri:c2=tri[A3];
[A3][4:a]acrossfade=d=10:c1=tri:c2=tri[audio] "
-vsync 0 -map "[output]" -map "[audio]" /tmp/media/final/some_filename_d0d2aab0-792a-4540-b2d3-e64abe98bf5c.mp4
And all works pretty well, but if I have, for example:
picture
video
video
picture
Then the sound from the second video is mapping to the first picture and sound from the third video to second video. And the third video actually goes without sound.
It seems like it's happening because the silent sound of the first picture is pretty short. An I right?
If so, how can I increase its duration?
I would much appreciate any help with this!
Assuming 5 inputs of 10 seconds each, all with audio streams*, with ffmpeg 4.3 or newer, use the xfade and acrossfade filters.
ffmpeg
-i in1.mp4
-i in2.mp4
-i in3.mp4
-i in4.mp4
-i in5.mp4
-filter_complex
" [0][1]xfade=transition=fade:duration=2:offset=8[V01];
[V01][2]xfade=transition=fade:duration=2:offset=16[V02];
[V02][3]xfade=transition=fade:duration=2:offset=24[V03];
[V03][4]xfade=transition=fade:duration=2:offset=32[video];
[0:a][1:a]acrossfade=d=2:c1=tri:c2=tri[A01];
[A01][2:a]acrossfade=d=2:c1=tri:c2=tri[A02];
[A02][3:a]acrossfade=d=2:c1=tri:c2=tri[A03];
[A03][4:a]acrossfade=d=2:c1=tri:c2=tri[audio]"
-vsync 0 -map "[video]" -map "[audio]" out.mp4
*if there's no existing audio stream, add one using the command in step 1.
If the existing audio stream of a file isn't 10 seconds long, use these filters on it before acrossfade.
[input]aresample=async=1:first_pts=0,apad,atrim=0:10[filtered]
and then use this filtered stream as input.

ffmpeg to calculate audio/visual difference between compressed and non-compressed video

I'm trying to calculate the audio + visual difference between a harshly compressed video file and one that hasn't been.
I'm using pipes because ultimately I wish this to take src from a camera stream.
I've managed to get the video results that I'm looking for, but I'm struggling with the audio.
I've added a line to invert the phase of the compressed audio, so that when they add up in the blend they should almost cancel each other out, but that doesn't happen.
ffmpeg -i input.avi -f avi -c:v libxvid -qscale:v 30 -c:a wmav1 - | \
ffmpeg -i - -f avi -af "aeval='-val(0)':c=same" - | \
ffmpeg -i input.avi -i - -filter_complex "blend=all_mode=difference" -c:v libx264 -crf 18 -f avi - | \
ffplay -
I can still hear all the audio, when what I should be hearing are solely compression artifacts. thx
To preface, I'm not sure your method would identify audio compression 'artifacts'
Your command doesn't perform any audio comparison, it only inverts a single channel. Also, the audio and video are compressed twice and the codecs the last ffmpeg command receives are the default AVI codecs of mpeg4 and mp3.
Use
ffmpeg -i input.avi -f matroska -c:v libxvid -qscale:v 30 -c:a wmav1 - |\
ffmpeg -i input.avi -i - -filter_complex "[0][1]blend=all_mode=difference;[1]aselect=gt(n\,0),asetpts=PTS-STARTPTS[1a];[0][1a]amerge,aeval=val(0)-val(1):c=mono" -c:v rawvideo -c:a pcm_s16le -f matroska - |\
ffplay -
I assume your audio is mono. If your audio has N channels, your aeval will need N expressions where the Mth expression is val(M-1)-val(N+M-1)
I also trim out the first encoded audio frame in order to mitigate encoder delay that Paul mentioned, and it seems to work here.
There might be some delay introduced with encoded audio samples. Also your command is incorrect.

Generate Video From Images and Audio

I have a list of images: 1.png, 2.png... and a list of audio files 1.mp3, 2.mp3...
I'd like to generate a video file where audio clips are concatenated, and each image is displayed over the corresponding audio clip:
Think of the images as slides in a slideshow, and the audio as narration for the slide.
Are there any frameworks which would allow me to do this? I'd like to use FFmpeg CLI or something high level if possible.
Lazy method is to make each segment then concatenate with the concat demuxer:
ffmpeg -loop 1 -i 1.png -i 1.mp3 -c:v libx264 -preset stillimage -vf format=yuv420p -c:a aac -shortest 1.mp4
ffmpeg -loop 1 -i 2.png -i 2.mp3 -c:v libx264 -preset stillimage -vf format=yuv420p -c:a aac -shortest 2.mp4
ffmpeg -loop 1 -i 2.png -i 2.mp3 -c:v libx264 -preset stillimage -vf format=yuv420p -c:a aac -shortest 2.mp4
ffmpeg -f concat -i input.txt -c copy -movflags +faststart output.mp4
This assumes the image files are the same width & height, and the audio files have the same channel layout & sample rate.
More complicated method is to use the concat filter which allows you to do it all in one command, but you'll have to enter the duration of each image segment to match the corresponding audio duration.

FFMPEG amix filter causes main audio stream to cut out

So I have a video called 1.mkv and would like to mix in a variety of different audio clips at certain points. To do this I'm using the -filter_complex option. However, I'm running into some problems because when ffmpeg tries to mix in the first audio stream the audio works for a short while when the clip is playing and then all audio cuts out. I'm running ffmpeg version 2.8.15-0(which is up to date with my distro). Another "weird" thing about the video output is that in xplayer the video will freeze after the audio cuts out, and will work if you skip far enough ahead in the video(not sure if this is helpful but it might give some extra clues).
Full command:
ffmpeg -i "1.mkv" -i "5.wav" -i "2.wav" -i "3.wav" -i "6.wav" -i "7.wav" -i "4.wav" -i "9.wav" -i "8.wav" -i "10.wav" -filter_complex "[0:0]setdar=4/3[v0];
[2:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=20000|20000,volume=0.5[ad2];
[4:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=900000|900000,volume=0.5[ad4];
[3:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=300000|300000,volume=0.5[ad3];
[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=720000|720000,volume=0.5[ad1];
[7:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1140000|1140000,volume=0.5[ad7];
[9:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1260000|1260000,volume=0.5[ad9];
[8:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=1020000|1020000,volume=0.5[ad8];
[5:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=960000|960000,volume=0.5[ad5];
[6:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=480000|480000,volume=0.5[ad6];
[0:1]volume=1[ad0];
[ad0][ad2][ad4][ad3][ad1][ad7][ad9][ad8][ad5][ad6]amix=inputs=10:duration=first:dropout_transition=0,dynaudnorm[a0]" -map "[v0]" -map "[a0]" -c:v libx264 -ar 44100 -c:a libmp3lame -preset ultrafast -crf 17 -b:v 1M out2.flv
partial command
ffmpeg -i "1.mkv" -i "2.wav" -filter_complex "[0:0]setdar=4/3[v0];
[1:a]aformat=sample_fmts=fltp:sample_rates=44100:channel_layouts=stereo,adelay=20000|20000,volume=0.5[ad2];
[0:1]volume=1[ad0];
[ad0][ad2]amix=inputs=2:duration=first:dropout_transition=0,dynaudnorm[a0]" -map "[v0]" -map "[a0]" -c:v libx264 -ar 44100 -c:a libmp3lame -preset ultrafast -crf 17 -b:v 1M out2.flv
So I managed to solve this by playing around with the audio filters. The fix was converting the mono stream into a stereo before applying the audio filters. I was considering deleting the question but I'll leave it up incase someone has the same problem in the future.
mono to stereo
[1][1]amerge=inputs=2[a1]

ffmpeg add all audio tracks to video conversion (mkv)

I have a script that takes in input a video file (generally avi or mp4) and converts it to a "lower quality" mkv video optimized for web streaming.
The ffmpeg command I use is this one:
ffmpeg -fflags +genpts -i file:"$input" -sn -codec:v:0 libx264 -force_key_frames expr:gte\(t,n_forced*5\) -vf "scale=trunc(min(max(iw\,ih*dar)\,1280)/2)*2:trunc(ow/dar/2)*2" -pix_fmt yuv420p -preset superfast -crf 23 -b:v 1680000 -maxrate 1680000 -bufsize 3360000 -vsync vfr -profile:v high -level 41 -map_metadata -1 -threads 8 -codec:a:0 libmp3lame -ac 2 -ab 320000 -af "aresample=async=1" -y "$output"
The problem is that this command only includes the first audio track of my video. I have some dual language videos (italian and english) for which I want to include both languages.
Is there a simple ffmpeg command option that automatically includes all audio tracks found in a video?
Add -map 0:a to include all audio streams.

Resources