Concat mp4 files with a command line tool - ffmpeg

I am blocked trying to do something, and I'm ready to make a donation if somebody can help me:
I try to concat http://s.serero.free.fr/rolex.mp4 video and http://s.serero.free.fr/video.mp4 video in one output mp4 file and I tried during a big time without results.
I want to concat http://s.serero.free.fr/rolex.mp4 + http://s.serero.free.fr/video.mp4
or http://s.serero.free.fr/video.mp4 + http://s.serero.free.fr/rolex.mp4.
I tried with ffmpeg command line software and with mp4box command line software, I think that I don't have the good method.
I tried to transform http://s.serero.free.fr/video.mp4 in the same format of http://s.serero.free.fr/rolex.mp4 (and vice versa):
I transformed http://s.serero.free.fr/rolex.mp4 with the same frame rate of http://s.serero.free.fr/video.mp4
I transformed http://s.serero.free.fr/rolex.mp4 with the same video bitrate of http://s.serero.free.fr/video.mp4
I transformed http://s.serero.free.fr/rolex.mp4 with the same video audio bitrate of http://s.serero.free.fr/video.mp4
Can somebody help me?
Explain to me what is wrong in my strategy?

Your input parameters vary, so you have to make them similar before concatenation.
rolex.mp4
Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 835 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
video.mp4
Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc), 1152x720, 1749 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, s16p, 127 kb/s (default)
This example will make video.mp4 more like rolex.mp4 then concat them:
ffmpeg -i rolex.mp4 -i video.mp4 -filter_complex \
"[1:v]pad=1280:720:(ow-iw)/2:0,fps=25,format=yuv420p[v1]; \
[0:v][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" output.mp4
You don't actually need to declare fps or format because, as the concat filter documentation states:
All corresponding streams must have the same parameters in all
segments; the filtering system will automatically select a common
pixel format for video streams, and a common sample format, sample
rate and channel layout for audio streams, but other settings, such as
resolution, must be converted explicitly by the user.
...but doing so will allow you to manually choose the "common" settings instead of relying on the filter automatically doing so and potentially selecting a setting you don't want.

Thanks for LordNeckbeard for his excellent answer, he just let a little mistake on the command, i just want to a little explanation :
If I want to concat video.mp4(1152X720) with rolex.mp4(1280X720), we must understand that "video.mp4" is the main video so the video(s) to concatene must have exactly the same frame size.
So before to do this operation you need to resize rolex.mp4 video with the same size like video.mp4 with ffmpeg :
ffmpeg -i rolex.mp4 -s 1152x720 -c:a copy newrolexsized.mp4
No video.mp4 and newrolexsized.mp4 has the same frame size, and you can use the command (spcifying pad=1152:720 => size of the main video):
ffmpeg -i video.mp4 -i newrolexsized.mp4 -filter_complex "[1:v]pad=1152:720:(ow-iw)/2:0,fps=25,format=yuv420p[v1];[0:v][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" -map "[v]" -map "[a]" out.mp4

Related

Concatenate no audio video with other videos containing audio,

I have a txt file which contains several videos:
file '01.mp4' # No audio, only video
file '02.mp4' # Video with audio
...
All my videos are using same video codecs:
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 720x1280, 3167 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
And all my video that contains audio are these codecs:
Stream #0:1[0x2](und): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 43 kb/s (default)
I tried to add silent audio using:
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -i 01.mp4 -c:v copy -c:a aac -shortest 01-silentaudio.mp4
But when concatening all my videos, it results in no audio for all videos.
What should I do?
Maybe I can reencode all my video to a specific codec, including my video without sound, in order to have the same codecs for all? What do you think?
Thank you

Is there a function to add a title to multiple videos? FFMPEG

I'm getting started with FFMPEG to add a title video to a few dozen videos I have. What would be the proper command to do this?
Use the concat demuxer
There are several methods to join/merge/concatenate one video to another. This method uses the concat demuxer in ffmpeg to join the title video to the main video. Although there are several steps, it has the advantage that it does not re-encode the video you are adding a title to. So the process is quick and the quality is preserved.
Example
See the attributes of the video you want to add a title video to. In this example it is named main.mp4. When making the title video you will need to ensure that it matches the attributes of the video you want to add a title to.
ffmpeg -i main.mp4
...
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 988 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Generate the title video. Make sure the title video matches the attributes of the main file so it can concatenate properly. This example uses the color and anullsrc source filters to make 5 seconds of black video and silent audio, and the drawtext filter to make text:
ffmpeg -f lavfi -i color=size=1280x720:rate=30000/1001:duration=5:color=black -f lavfi -i anullsrc=sample_rate=44100:channel_layout=stereo -vf "drawtext=text='your title':fontcolor=white:fontsize=48:x=(w-text_w)/2:y=(h-text_h)/2" -c:v libx264 -profile:v main -c:a aac -shortest title.mp4
Make a text file named input.txt. This will be used by the concat demuxer and lists the files that you want to concatenate.
file 'title.mp4'
file 'main.mp4'
Finally, concatenate the title video to the main video with the concat demuxer:
ffmpeg -f concat -i input.txt -c copy output.mp4
Batch mode
ffmpeg does not have a batch mode to automatically do this for a folder of videos. However, it can be done with shell scripting but that is a whole new topic that deserves its own question. See How do you convert an entire directory with ffmpeg? for some examples.

How to process a video to mp4 with ffmpeg for quality and compatibility?

I am beginning to be more serious about video. I am processing my videos with ffmpeg in a fully updated Linux into mp4 to use it in HTML5 directly.
Now, I have old AVI videos that I want to convert to mp4 with ffmpeg for use with HTML5. In particular, I have this one:
http://luis.impa.br/photo/1101_aves_ce/caneleiro-de-chapeu-preto_femea_Quixada-CE-110126-E_05662+7a.avi
(I know, terrible quality... sorry). According to ffprobe:
Duration: 00:01:35.30, start: 0.000000, bitrate: 1284 kb/s
Stream #0:0: Video: mpeg4 (Simple Profile) (DX50 / 0x30355844), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 1144 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, s16p, 128 kb/s
That seems perfect: mpeg4 video and mp3 audio. So I tried:
ffmpeg -i input.avi -acodec copy -vcodec copy output.mp4
It generates a file that plays nicely in mplayer, but not in firefox getting an error:
Video format or MIME type not supported.
Chrome plays the audio, but no video is shown... Now, if I do:
ffmpeg -i input.avi output.mp4
firefox works, but the video is reencoded in another one with half the size (half the bitrate). This is what ffprobe says about the reencoded video:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.71.100
Duration: 00:01:35.30, start: 0.000000, bitrate: 685 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 548 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
I suppose that I am loosing lots of quality (and time processing the video). So, my questions:
Why are browsers not playing my video with the copy codecs ?
Can I work with ffmpeg in this particular file without reencoding? If yes, how?
If I need to reencode, which are "reasonable" parameters to keep close to the original quality? Would something like
ffmpeg -i input.avi -b:v 1024k -bufsize 1024k output.mp4
suffice for this video? This generates a new video with size closer to the original one.
Thanks!
According to ffprobe and if I see it correctly, you have a DivX (5) video file. Do not use it for web!! ;)
mpeg4 (Simple Profile) (DX50 / 0x30355844)
So I don't see any chance to use this video without reencoding. Not if you wish to support firefox.
Use WebM or h264: https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
UPDATE
Good settings for reencode depends on your input (bitrate, resolution, fps, kind of material ...), so there is no standard answer.
But you have to specify a codec or ffmpeg choose one depending on your output file extension (so it can be the wrong one).
You can try this:
ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv
Presets and tunes can help to find the best choice: https://trac.ffmpeg.org/wiki/Encode/H.264

FFmpeg - selecting appropriate bitrate for VP9 encoding

I am looking to encode a 4k video shot with iPhone 6s in VP9 in the best quality possible.
For reference, stream data of the video I would like to encode, via ffprobe:
Duration: 00:00:10.48, start: 0.000000, bitrate: 46047 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 3840x2160, 45959 kb/s, 29.98 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
Metadata:
creation_time : 2017-03-13T21:12:56.000000Z
handler_name : Core Media Data Handler
encoder : H.264
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 79 kb/s (default)
Metadata:
creation_time : 2017-03-13T21:12:56.000000Z
handler_name : Core Media Data Handler
I am using the following FFmpeg commands, based on these instructions (see Best Quality (Slowest) Recommended Settings section).
ffmpeg -i INPUT.mov -c:v libvpx-vp9 -pass 1 -b:v 46000K -threads 4 -speed 4 -g 9999 -an -f webm -y /dev/null
ffmpeg -I INPUT.mov -c:v libvpx-vp9 -pass 2 -b:v 46000K -threads 4 -speed 0 -g 9999 -an -f webm OUTPUT.webm
Is there a best practice to select an optimal -b:v value such that the resulting video is visually indistinguishable from the original? I have tried values ranging from 36000K-46000K, but these result in massive files with an overall bitrate exceeding the target bitrate.
Thanks in advance!
Just have to experiment with different, much lower bit rates, and view the results. I try to watch for artifacts. Does hair still look good? Cloth? Lettering, like on road signs and store windows? No blockiness? No bleeding of dark and light at sharp edges? No echoes? I find motion blur in the original hard to judge, have to compare side by side to tell the difference between that and compression artifacts.
Try 1/10th of 36000k. I find vp9 at a nominal 400k bit rate works great on 1280x720 video. (ffmpeg with libvpx-vp9 overshoots, and I typically end up with a 20% higher actual bit rate, 480k) 4K is 3840x2160, 9x the size of 1280x720, so it would seem a 3600k bit rate should produce good results.
Another guide is that vp9 is reportedly about equal in quality to mp4 at half the bit rate. Video that looks good at a 1000k bit rate in mp4 should look good at 500k in vp9.

ffmpeg - whatsapp: video format not supported

I have two videos (.mp4) files. One uploads to whatsapp and another does not.
Using ffmpeg I checked their properties:
a) Properties of video which uploads:
Duration: 00:00:56.45, start: 0.148000, bitrate: 1404 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1080x1080, 1359 kb/s, 23.98 fps, 23.98 tbr, 90k tbn, 47.95 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(eng): Audio: aac (HE-AACv2) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 47 kb/s (default)
Metadata:
handler_name : SoundHandler
At least one output file must be specified
b) video which does not upload to whatsapp (because its says format not supported)
Duration: 00:00:56.10, start: 0.000000, bitrate: 543 kb/s
Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p, 1080x1080 [SAR 1:1 DAR 1:1], 464 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 47.95 tbc
Stream #0:1: Audio: aac (LC) ([255][0][0][0] / 0x00FF), 48000 Hz, stereo, fltp, 56 kb/s
The difference in video I noticed:
(avc1 / 0x31637661) vs (H264 / 0x34363248)
1359 kb/s vs 464 kb/s
90k tbn vs 23.98 tbn
What can be the reason?
Also the second video is not being played in Android.
The link for the video is https://drive.google.com/open?id=0B4UM6vTHw4pyMExQQ1lxZGp0N2c
There are some options for a better compatibility:
ffmpeg -i broken.mp4 -c:v libx264 -profile:v baseline -level 3.0 -pix_fmt yuv420p working.mp4
With -profile:v baseline -level 3.0 you make the file more compatible with most older players, including WhatsApp ;). Although, this disables some advanced features.
-pix_fmt yuv420p is necessary to compile to baseline (YUV planar color space with 4:2:0 chroma subsampling).
Also, you can adjust other options as bitrate, framerate, audio, etc.
Source: H.264 docs
Copied from https://www.reddit.com/r/ffmpeg/comments/564kyc/ffmpeg_whatsapp_video_format_not_supported/?st=ivjxdi0v&sh=848ce7eb
ffmpeg -i brokenvideo.mp4 -c:v libx264 -c:a aac fixedvideo.mp4
Also had to apply this fix: FFMPEG (libx264) "height not divisible by 2"
This is worked for me in 2020
ffmpeg -i broken.mp4 -c:v libx264 -profile:v high -level 3.0 -pix_fmt yuv420p -brand mp42 fixed.mp4
I tried all previous commands and I got some errors. I was able to encode my video using this command and here is the explanation and why I set it up like this for a better compatibility:
ffmpeg -i input.mp4 \
-c:v libx264 -pix_fmt yuv420p \
-profile:v baseline -level 3.0 \
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" -vb 1024k \
-acodec aac -ar 44100 -ac 2\
-minrate 1024k -maxrate 1024k -bufsize 1024k \
-movflags +faststart \
output.mp4
If your input contains AAC audio you can stream copy instead of re-encoding by changing -acodec aac -ar 44100 -ac 2 to -acodec copy to preserve the audio quality.
option
explanation
-vcodec libx264
Chooses video encoder libx264
-pix_fmt yuv420p
Ensures YUV 4:2:0 chroma subsampling for compatibility
-profile:v baseline
Set the encoding profile to baseline. Used primarily for low-cost applications that require additional data loss robustness
-level 3.0
Set the operating point level to 3.0 which is necessary to have compatibility with WhatsApp
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"
If you get not divisible by 2 error see
-acodec aac
Chooses audio encoder aac
-minrate 1024k
set min bitrate tolerance to 1024k (in bits/s). It is of little use elsewise
-maxrate 1024k
set max bitrate tolerance to 1024k (in bits/s). Requires bufsize to be set
-bufsize 1024k
set rate-control buffer size to 1024k (in bits)
-movflags +faststart
enables fast start for streaming
Note about faststart
Normally, a MP4 file has all its metadata packets stored at the end of the file, in data units named atoms. The mdat atom is located before the moov atom. If the file is created by adding the -movflags faststart, the moov atom is moved at the beginning of the MP4 file. By using this option, the moov atom is located before the mdat atom. This allows video playback to begin before the file has been completely downloaded.
2023-01-22 I used the most upvoted answer format and it worked for video, but audio was not working on iPhones. Here's what worked for me:
ffmpeg -i broken.mp4 -c:v libx264 -profile:v baseline -level 3.0 -pix_fmt yuv420p -ac 2 working.mp4
I had to add -ac 2 because the audio format I had wasn't seen as stereo by iOS.

Resources