I'm trying to convert HEVC videos to VP9 so they can be played in a web browser while keeping file size roughly the same.
I am struggling to create a video with similar quality/file size.
Here's the stream info for one of the HEVC videos the video is is 22:49 and 168.7mb:
Stream #0:0(und): Video: hevc (Main) (hev1 / 0x31766568), yuv420p(tv, bt709), 1920x1080, 900 kb/s, 23.98 fps, 23.98 tbr, 90k tbn, 23.98 tbc (default)
The bitrate is 900K so I had thought that the following command would use the same bitrate and give a roughly similar image quality:
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -vaapi_device /dev/dri/renderD128 -i "$infile" -vf 'format=nv12,hwupload' -c:v vp9_vaapi -b:v 900K -bf 2 -bsf:v vp9_raw_reorder,vp9_superframe -c:a libvorbis "$outfile"
Using this, the quality is noticeably much, much worse and busy scenes look incredibly blocky though the file size is roughly equivalent to the HEVC source.
If I omit the bitrate and let VP9 work it out
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -vaapi_device /dev/dri/renderD128 -i "$infile" -vf 'format=nv12,hwupload' -c:v vp9_vaapi -b:v 0 -bf 2 -bsf:v vp9_raw_reorder,vp9_superframe -c:a libvorbis "$outfile"
The quality is visually indistinguishable but the file size of the VP9 converted video reaches 401mb, up from 168mb of the HEVC file and during encoding the bitrate is over 3m for most of the video.
I tried going up to 1.2M (33% higher than the source video) and VP9 still gave a very blocky looking video.
Is VP9 really that much worse than HEVC or is there an option I am missing? or is it because I am converting from HEVC?
Related
I tried it with ffmpeg.
ffmpeg input.webm output.webp
input.webm contains transparent background and But the alpha channel becomes white in webp. I think that means alpha channel doesn't come together.
I extracted frames with this command:
ffmpeg -i input.xxx -c:v libwebp output_%03d.webp
And it also gives me webp files with white background.
How can I convert it properly with alpha channel? OR should I convert it from other format(extension)?
Use the -c:v libvpx option before the input to change the decoder like in this example for the first frame (-frames:v 1):
ffmpeg -c:v libvpx -i input.webm -frames:v 1 -c:v libwebp -y output.webp
This comment says that:
FFmpeg's native VPx decoders don't decode alpha. You have to use the libvpx decoder
You can check your decoders using ffmpeg -decoders | grep libvpx and you should see an output like this:
V....D libvpx libvpx VP8 (codec vp8)
V....D libvpx-vp9 libvpx VP9 (codec vp9)
According to that output, libvpx would be the decoder for VP8 and libvpx-vp9 for VP9.
You can check the codec of your video using ffprobe input.webm. You should see an output like this:
Stream #0:0(eng): Video: vp8, yuv420p(progressive), 640x360, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
Metadata:
alpha_mode : 1
For converting a whole webm (VP8) to an animated webp use:
ffmpeg -c:v libvpx -i input.webm output.webp
For converting a whole webm (VP9) to an animated webp use:
ffmpeg -c:v libvpx-vp9 -i input.webm output.webp
I have an MXF video
I googled syntax to convert to mov and ran it in Mobaxterm on Win10.
"/drives/c/Program Files (x86)/ffmpeg/bin/ffmpeg.exe" -i Clip0001.MXF -c:v libx264 -c:a aac -ab 384k -sn -strict -2 output.mov
I view it in VideoLan and it looks great.
I load it into Magix Movie Studio 15 and audio is fine, but video is green!
ffmpeg output.mov....shows me:
Stream #0:0(eng): Video: h264 (High 4:2:2) (avc1 / 0x31637661), yuv422p, 1920x1080 [SAR 1:1 DAR 16:9], 4530 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Even this does not work:
ffmpeg.exe -i Clip0001.MXF output.mov
Any suggestions on converting this?
Edit1:
Here is what it looks like in the editor:
Edit2:
Try this and it works, but quality is terrible.
ffmpeg.exe" -i Clip0001.MXF -c:v mpeg4 -c:a aac -ab 384k -sn -strict -2 output.mov
FFmpeg isn't failing; many video editors usually have limited-capability H264 decoders.
Your input has 4:2:2 chroma subsampling and ffmpeg will preserve that when it can. Here, it can and does. However, your video editor can only deal with 4:2:0 subsampled H264 streams.
So, use
ffmpeg.exe -i Clip0001.MXF -pix_fmt yuv420p -c:v libx264 -c:a aac -b:a 384k -sn output.mov
If this command throws an error for the AAC encoder due to the missing -strict -2, your ffmpeg is very old (> 3 years). You should upgrade.
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
I was recording something with vlc off v4l2 (in case that makes a difference), and I just selected the first format that worked, being mpeg2 using TS container. File resulted in .ts extension, as automatically selected by vlc. When I then tried to put the video file in my video editor, it said the video was 19,884 hours long, when it should be about 6 minutes (it is ~80mb in size). When I try to play it in xine, it correctly shows the duration (vlc doesn't), and when I use ffprobe:
[mpegts # 0x9b2c0a0] max_analyze_duration 5000000 reached at 5000000
Input #0, mpegts, from 'loopbacktestcap.ts': Duration: N/A, start:
17978.139456, bitrate: N/A Program 1
Stream #0:0[0x44](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30
tbr, 90k tbn, 60 tbc
Stream #0:1[0x46](): Video: mpeg2video ([2][0][0][0] / 0x0002), 90k tbn
Notice especially this line:
Duration: N/A, start: 17978.139456, bitrate: N/A Program 1
I looked it up and it seems the lack of duration has to do with the container. But I have tried a few things to reencode (I tried -vcodec copy, mpeg2, libx264...) and all I can get is 20 second files of 1.1mb - 1.8mb.
So how can I reencode this file so the duration appears, and I get the full 6 minutes, instead of just the first 20 seconds?
First milestone was reached when I found this link: Map - ffmpeg -- Example #8 which led me to try:
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts
Yielding the following:
[mpegts # 0x9980f40] max_analyze_duration 90000000 reached at 90000000
Input #0, mpegts, from 'loopbacktestcap.ts':
Duration: 00:16:00.96, start: 17978.139456, bitrate: 695 kb/s
Program 1
Stream #0:0[0x44](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
Stream #0:1[0x45](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
Stream #0:2[0x46](): Video: mpeg2video (Main) ([2][0][0][0] / 0x0002), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc
Notice that it now gives me the correct duration as well as an extra stream and more info on the second one (which is technically the third one). So then I ran:
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts -map 0 -c copy map0.mp4
and that now produced a 79451050 byte file map0.mp4, where my_mpeg2_file.ts is 83499636. I try to play this in vlc, and it shows the duration as 9:12, but if I jog the play position, two more vlc windows are opened and vlc begins to act strange; the video display area is hung, though the playback position indicator continues to progress. This might be just a buggy vlc, but I am stuck at this point. Let me know if anyone sees anything I am missing here.
xine however cannot play back the new file (where it plays the original and shows that it is 6 minutes long -- actually, the duration counter goes a little nutty as I play the file and changes constantly, so I don't know).
So, next command I tried was:
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts -map 0 -c libx264 map0x264.mp4
Trying to play the resulting file (43652975 bytes, for the curious) led to the same strange behavior in vlc, where now I can see that it is opening a new window for each stream, and playing the stream when it is its "turn" in its respective window, freezing the other display areas of the other windows. Trying to close them stops playback for all and closes the two extra windows. I am guessing keeping all 3 streams in the same file is nonsense.
SUCCESS!
Next attempt was:
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts -map 0:0 -c copy map0_0.ts
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts -map 0:1 -c copy map0_1.ts
ffmpeg -probesize 90M -analyzeduration 90M -i my_mpeg2_file.ts -map 0:2 -c copy map0_2.ts
which resulted in files of size:
4912 map0_0.ts
5372 map0_1.ts
74728 map0_2.ts
map0_0.ts is 20 seconds long, map0_1.ts is a still image 1:12 long, and map0_2.ts is 9:12. Exactly what I wanted! And my video editor accepts them no problem. SOLVED!
I had a similar challenge of supporting transport stream (ts) video files in our video processing infrastructure. I used ffmpeg to convert ts into mp4 files with two-pass encoding.
The command(s) in its full length:
Pass 1:
ffmpeg -i camera.ts -filter:v scale=-1:480,setsar=1/1 -pix_fmt yuv420p -threads 0 -r 25/1 -force_fps -c:v libx264 -profile:v baseline -preset slow -x264opts level=3.0:ref=1 -b:v 1000k -maxrate 1000k -bufsize 2000k -s hd480 -c:a libfaac -ar 16000 -ac 2 -ab 128000 -pass 1 -movflags faststart -y video.mp4
Pass 2:
ffmpeg -i camera.ts -filter:v scale=-1:480,setsar=1/1 -pix_fmt yuv420p -threads 0 -r 25/1 -force_fps -c:v libx264 -profile:v baseline -preset slow -x264opts level=3.0:ref=1 -b:v 1000k -maxrate 1000k -bufsize 2000k -s hd480 -c:a libfaac -ar 16000 -ac 2 -ab 128000 -pass 2 -movflags faststart -y video.mp4 >>& ffmpeg.log
I downscale the video to hd480 (852x480) reencoding the video stream with libx264 baseline level 3 with a relatively low bitrate as well as audio with libfaac and moving the moov atom to the beginning of the file for web compatibility (-movflags faststart)
See the FFMpeg documentation for all details on the flags.
Note that I just dug up this command which works for our setup: processing transport stream recordings from IP cameras. You would probably need to specifically adapt resolution and bitrates to your needs. Hope this points you in the right direction.
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.