How to combine 2 video files and audio file with FFMPEG? - file

I am attempting to use ffmpeg exe to combine 2 video files and 1 audio. I wanted the audio to play over "inputFile.mp4" and not over the "outroFile.mp4" is this possible? Currently this is what I have. But Im not sure if what im doing wrong or what I need to get it right.
ffmpeg -i "inputFile.mp4" -i "outroFile.mp4" -i "audioFile.mp3" -threads 4 -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" -map "[v]" -map "[a]" "outputFile.mp4"
Can you please help me with this?

This can be done in two steps.
#1
ffmpeg -i "inputFile.mp4" -stream_loop -1 -i "audioFile.mp3" -map 0:v -map 1:a -c copy -shortest inputwithaudio.mp4
#2
ffmpeg -i inputwithaudio.mp4 -i outrofile.mp4 -threads 4 -filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" -map "[v]" -map "[a]" "outputFile.mp4"
You'll need a recent version of ffmpeg, preferably 4.0, as there's a bug with stream_loop in earlir versions.

Related

ffmpeg complex filter pip loop not working

I am using an ffmpeg complex filter to:
turn a number of images into a slideshow
scale the slideshow to 1/6th of its original size
loop the slideshow infinitely
set the looping slideshow as a picture-in-picture over another looping video
then add audio from another file which determines the maximum length of the final video.
Everything is working except step 3.
Here is my code (broken down into individual lines):
ffmpeg -y
-loop 1 -t 5.5 -i /uploads/2021/07/slide04-scaled.jpg
-loop 1 -t 5.5 -i /uploads/2021/07/Slide05-scaled.jpg
-loop 1 -t 5.5 -i /uploads/2021/07/Slide06-scaled.jpg
-i /slowwmo-videos/intro.mp4
-i /uploads/2021/07/busy_bees_01.mp3
-filter_complex
"
[1]fade=d=0.5:t=in:alpha=1,setpts=PTS-STARTPTS+5/TB[a1];
[2]fade=d=0.5:t=in:alpha=1,setpts=PTS-STARTPTS+10/TB[a2];
[0][a1]overlay[b2];
[b2][a2]overlay[slides];
[slides]loop=loop=-1,scale=iw/6:ih/6,format=yuv420p,fps=fps=25[pip];
[3][pip]overlay=W-w-100:200[v]
"
-map [v]:v:0 -map 4:a:0 -vcodec libx264 -profile:v main -video_track_timescale 25000 -pix_fmt yuv420p -s 1280x720 -acodec aac -af aresample=44100 -shortest /slowwmo-videos/busy_bees/7494.ts
ffmpeg -y
-framerate 25 -loop 1 -t 5.5 -i /uploads/2021/07/slide04-scaled.jpg
-framerate 25 -loop 1 -t 5.5 -i /uploads/2021/07/Slide05-scaled.jpg
-framerate 25 -loop 1 -t 5.5 -i /uploads/2021/07/Slide06-scaled.jpg
-stream_loop -1 -i /slowwmo-videos/intro.mp4
-i /uploads/2021/07/busy_bees_01.mp3
-filter_complex
"[0][1]xfade=transition=fade:duration=0.5:offset=5[fade];
[fade][2]xfade=transition=fade:duration=0.5:offset=9.5,scale=iw/6:-1,loop=loop=-1:size=375[pip];
[3:v]scale=1280:720[bg];[bg][pip]overlay=W-w-100:200,format=yuv420p[v]"
-map "[v]" -map 4:a -c:v libx264 -c:a aac -shortest output.ts
Use -stream_loop to loop intro.mp4
The loop filter needs you to tell it how many frames to loop.
xfade offers more transition effects and eliminates the need for additional setpts and overlay. To figure out offset timing see Merging multiple video files with ffmpeg and xfade filter.

Batch Script to Download Video with youtube-dl and Convert with FFmpeg

I'm trying to
Using a single batch script to
Download an mp4 video using youtube-dl
Save the video's original title to a batch variable
Convert the video to webm with FFmpeg
I want to keep the original title, so it needs to read the title with youtube-dl, save it to a variable, and use that variable for FFmpeg input/output filename.
CMD Batch
1. Download Video
youtube-dl -f best "https://www.youtube.com/watch?v=TWNhqCHw0qc" -o "C:\Users\Matt\Downloads\%%(title)s.mp4" --merge-output-format mp4
2. Download Video using Loop
This is used to save the title to a variable %%a.
for /f "delims=" %%a in ('youtube-dl -f best "https://www.youtube.com/watch?v=TWNhqCHw0qc" -o #"C:\Users\Matt\Downloads\%%(title)s.mp4" --merge-output-format mp4') do (echo example)
3. Final Script
Download Video, Save Title, Convert with FFmpeg
Sorted
for /f "delims=" %%a in ('
youtube-dl
-f best "https://www.youtube.com/watch?v=TWNhqCHw0qc"
-o #"C:\Users\Matt\Downloads\%%(title)s.mp4"
--merge-output-format mp4
')
do (ffmpeg -y
-i "C:\Users\Matt\Downloads\%%a.mp4"
-c:v libvpx -b:v 1300K -crf 16 -pix_fmt yuv420p
-map 0:v:0? -sn
-c:a libvorbis -q:a 6 -ac 2 -map 0:a:0?
-f webm
"C:\Users\Matt\Downloads\%%a.webm"
)
Inline
for /f "delims=" %%a in ('youtube-dl -f best "https://www.youtube.com/watch?v=TWNhqCHw0qc" -o #"C:\Users\Matt\Downloads\%%(title)s.mp4" --merge-output-format mp4') do (ffmpeg -y -i "C:\Users\Matt\Downloads\%%a.mp4" -c:v libvpx -b:v 1300K -crf 16 -pix_fmt yuv420p -map 0:v:0? -sn -c:a libvorbis -q:a 6 -ac 2 -map 0:a:0? -f webm "C:\Users\Matt\Downloads\%%a.webm")
Error
Before the script can ever reach FFmpeg, youtube-dl fails to download the file. It says the file has already been downloaded, even when there is no file in the directory.
[download] #C#\Users\Matt\Downloads\Color Balloons.mp4 has already
been downloaded
I was able to create a script that works.
One of the problems was that youtube-dl wasn't working properly if located in C:\Program Files\, but works when located somewhere that doesn't require Administrator Privileges.
The --get-filename part requires an # symbol before the youtube-dl path.
youtube-dl gets filename from video and saves to var %%f
youtube-dl downloads the video to C:\Path\To\Downloads\
Merge output as mp4, so you can specify the extension for FFmpeg input
FFmpeg converts video to webm and uses %%f as input/output filename.
for /f "delims=" %%f in ('
#"C:\Users\Matt\Desktop\youtube-dl.exe"
--get-filename -o "%%(title)s"
"https://www.youtube.com/watch?v=TWNhqCHw0qc"
')
do ("C:\Users\Matt\Desktop\youtube-dl.exe"
-f best "https://www.youtube.com/watch?v=TWNhqCHw0qc"
-o "C:\Users\Matt\Downloads\%%f.mp4"
--merge-output-format mp4
&&
ffmpeg -y
-i "C:\Users\Matt\Downloads\%%f.mp4"
-c:v libvpx
-b:v 1300K -crf 16
-pix_fmt yuv420p
-map 0:v:0?
-sn
-c:a libvorbis
-q:a 6
-map 0:a:0?
-f webm
"C:\Users\Matt\Downloads\%%f.webm"
)

Workaround to .ts files in video merging?

I've got these sentences of code that I use for video processing, the first one adds a watermark, the second creates a .ts file of the watermarked video and then adds an intro and outro to it but I found that it quickly fills disk space because of the .ts files being used, is there a way to achieve the same results without them? Either by deleting them right after using them or by using a different process altogether.
for %%I in ("C:\Users\Administrator\Desktop\work\*.mp4") do ffmpeg.exe
-y -i "%%I" -i white.png -filter_complex "[0:v]scale=iw:ih[v0];[1:v][v0]scale2ref=iw/6:ih/18[logo][0v];[0v][logo]overlay=W-w-3:H-h-1[v]"
-map "[v]" -map 0:a -codec:v libx264 -preset ultrafast -crf 23 -codec:a copy "C:\Users\Administrator\Desktop\Complete-videos\%%~nI.mp4"
for %%I in ("C:\Users\Administrator\Desktop\Complete-videos\*.mp4") do ffmpeg -y
-i %%I -c copy -vbsf h264_mp4toannexb -f mpegts -s 1280*720 %%I.ts && ffmpeg -y -i "concat:out1.ts|%%I.ts|out1.ts" -c:v libx264 -strict experimental -bsf:a aac_adtstoasc -ar 48000 -r 20 "C:\Users\Administrator\Desktop\Complete-videos\%%~nI.mp4
pause
This does it in one command, with no intermediate files.
for %%I in ("C:\Users\Administrator\Desktop\work\*.mp4") do ffmpeg.exe
-y -i "%%I" -i white.png -i out1.ts -filter_complex "[1:v][0:v]scale2ref=iw/6:ih/18[logo][0v];[0v][logo]overlay=W-w-3:H-h-1,scale=hd720,setsar=1[vl];[2:v][2:a][vl][0:a][2:v][2:a]concat=n=3:v=1:a=1[v][a]"
-map "[v]" -map "[a]" -r 20 -c:v libx264 -ar 48000 "C:\Users\Administrator\Desktop\Complete-videos\%%~nI.mp4"
pause
Notes: Depending on where out1.ts is, you may have to specify its full path during input. In the first command, in your 2nd step, the size option has no effect as you're copying streams. If resize is needed, insert scale=hd720 after the concat filter in my command. Add -strict experimental if your ffmpeg is older than Dec 2015 and you don't want to upgrade.
[totally untried suggestion since I have no idea what the ffmpeg line is doing]
I suggest you try this on a small file subset on a device with a restricted space like a ramdrive or a usb drive. USB drive may take a while. Coffee is good.
for %%I in ("C:\Users\Administrator\Desktop\work\*.mp4") do (
ffmpeg.exe -y -i "%%I" -i white.png -filter_complex "[0:v]scale=iw:ih[v0];[1:v][v0]scale2ref=iw/6:ih/18[logo][0v];[0v][logo]overlay=W-w-3:H-h-1[v]"
-map "[v]" -map 0:a -codec:v libx264 -preset ultrafast -crf 23 -codec:a copy "C:\Users\Administrator\Desktop\Complete-videos\%%~nI.mp4"
for %%Q in ("C:\Users\Administrator\Desktop\Complete-videos\%%~nI.mp4") do ffmpeg -y
-i %%Q -c copy -vbsf h264_mp4toannexb -f mpegts -s 1280*720 %%Q.ts && ffmpeg -y -i "concat:out1.ts|%%I.ts|out1.ts" -c:v libx264 -strict experimental -bsf:a aac_adtstoasc -ar 48000 -r 20 "C:\Users\Administrator\Desktop\Complete-videos\%%~nQ.mp4
del *.ts
)
pause
This way, the first loop using %%I selects the file to be processed and apparently puts the processed file in another directory then immediately performs the second process on that file, controlled by %%Q using the name in %%~nI to select the single file created by the previous process.
Consequently, instead of processing 10 files each with its own .ts set, one is processed at a time and only one .ts set is created. I don't know whether the second process deletes the .ts files, but I've added a del to get rid of them on each cycle. I've also no idea whether the first process creates the .ts files, but I've made that assumption.
As the educationalists said about "new maths" - it's the idea that's important.

How to Batch Convert with FFmpeg 2 Pass?

I'm converting webm to mp4 using FFmpeg.
My batch file is
cd "C:\Users\Matt\Desktop\" && for %f in (*.webm) do ffmpeg -y -i "C:\Users\Matt\Desktop\%~f" -vcodec libx264 -b:v 600K -pass 1 -acodec aac -b:a 128k "C:\Users\Matt\Desktop\%~nf.mp4" && ffmpeg -y -i "C:\Users\Matt\Desktop\" -vcodec libx264 -b:v 600K -pass 2 -acodec aac -b:a 128k "C:\Users\Matt\Desktop\%~nf.mp4"
It works for CRF and 1 Pass, but using 2 Pass it stops on the second pass and gives the error:
C:\Users\Matt\Desktop" -vcodec libx264 -b:v 600K -pass 2 -acodec aac -b:a 128k C:\Users\Matt\Desktop\video: Invalid argument
The first double quote is missing on the Path, and the filename "video 01.mp4" is cut off.
Your code could only work in cmd directly, in a batch you have to double the percent signs of the for variable.
There is no need for a one liner in a batch.
I hope this is more clear and works.
#Echo off
Pushd "C:\Users\Matt\Desktop\"
for %%f in (*.webm) do (
ffmpeg -y -i "%%~f" -vcodec libx264 -b:v 600K -pass 1 -acodec aac -b:a 128k -f mp4 NUL
ffmpeg -y -i "%%~nf_tmp.mp4" -vcodec libx264 -b:v 600K -pass 2 -acodec aac -b:a 128k "%%~nf.mp4"
)
PopD
Pause

How to download/convert multiple streams to multiple outputs with FFmpeg?

Let's say I have 20 different online stream videos (playlist.m3u8) and I want every video to output to their own .avi files. How can I do that in single file, so I don't have to download and convert every single one separately?
I found a -map command online, but didn't get straight answer to this.
Will this be a working code?
ffmpeg -i 1playlist.m3u8 -vf scale=768:-1 -vcodec libx264 -crf 24 -acodec copy -map 0 1.avi \
-i 2playlist.m3u8 -vf scale=768:-1 -vcodec libx264 -crf 24 -acodec copy -map 1 2.avi \
-i 3playlist.m3u8 -vf scale=768:-1 -vcodec libx264 -crf 24 -acodec copy -map 2 3.avi

Resources