Prepare a video for low-performance hardware - performance

I'm trying to play some videos (webm mostly) on some very-low performance hardware. The hardware can barely handle FullHD output.
Since the devices in question are online via 3G modem only, there is some weight on the video size as well. However right now, the playing performance is definitely the more important part.
So, here's the question: Are there any options for avconv to improve playback performance? Or should I simply use another codec instead?
Right now, the command used is something like the following:
avconv \
-i $input_file \
-y \
-vf scale=$scale \
-an \
$output_file

You would want to use ffmpeg instead of avconv (ffmpeg is more active and reliable - my opinion):
Compile ffmpeg with libvpx support (WebM): guide
I would suggest you use CBR encoding
Set --profile to 3: guide, read about some more options if you want
Generally you would want to lower frame resolution and frame per second as much as acceptable for your project requirement and throw the appropriate bitrate for it.

There is an approach that you can try, that is to shrink the video twice in hight while leaving the width alone:
$ avconv -i 01.webm -vf 'scale=w=iw:h=ih/2' -c:v libtheora -c:a copy 01.ogv
for me has produced a file 84% the size of
$ avconv -i 01.webm -c:v libtheora -c:a copy 01.ogv
This way is much better than scalink in width, because it does not damage the text that may appear on the screen quite as much (human brain can for whatever reason deal with vertical distortion easier than with horizontal one).
You can also apply the denoise filter hqdn3d, which will make the filesize smaller, but will not damage the quality of the video.
The load on the processor of the playing machine can sometimes be more difficult to predict when one goes from video to video; but there is a difference in codecs. I've not compared them much, so can't offer real assistance.

Related

Optimally using hevc_videotoolbox and ffmpeg on OSX

I'm using ffmpeg 4.3.1 to convert videos from h264 to h265 and initially I was excited to discover that I can use my Mac's GPU to speed up the conversion with the flag hevc_videotoolbox.
My Mac hardware is the 10th generation Intel i5 with AMD Radeon Pro 5300
I'm using this command:
ffmpeg -i input_h264.mp4 -c:v hevc_videotoolbox -b:v 6000K -c:a copy -crf 19 -preset veryslow output_h265.mp4
The conversion speeds increased from 0.75x to 4x, almost a 500% improvement !
But then I noticed large filesizes and slightly fuzzy results. Then I noticed that changing the crf or the preset makes no difference, ffmpeg seems to ignore those settings. The only setting that seems to work is the video bit rate (-b:v).
So I started to google around to see how I could get better results.
But except for a few posts here and there, I'm mostly coming up blank.
Where can I get documentation on how to get better results using hevc_videotoolbox?
How can I find out what settings work and which ones are ignored?
Use the constant quality mode of videotoolbox on Apple Silicon to achieve high speed, high quality and small size. This works from FFmpeg 4.4 and higher — it's based on this commit.
Note that this does not work with Rosetta 2.
Compile ffmpeg for macOS or use ffmpeg from Homebrew (brew install ffmpeg)
Run with -q:v 65. The value should be 1-100, the higher the number, the better the quality. 65 seems to be acceptable.
For example:
ffmpeg -i in.avi -c:v hevc_videotoolbox -q:v 65 -tag:v hvc1 out.mp4
Listing options
Run ffmpeg -h encoder=hevc_videotoolbox to list options specific to hevc_videotoolbox.
Use -b:v to control quality. -crf is only for libx264, libx265, libvpx, and libvpx-vp9. It will be ignored by other encoders. It will also ignore -preset.
hevc_videotoolbox isn't as good as libx265, but it is fast
Like most hardware accelerated encoders, hevc_videotoolbox is not as efficient as libx265. So you may have to give it a significantly higher bitrate to match an equivalent quality compared to libx265. This may defeat the purpose of re-encoding from H.264 to HEVC/H.265.
Avoid re-encoding if you can
Personally, I would avoid re-encoding to prevent generation loss unless the originals were encoded very inefficiently and drive space was more important.
VideoToolBox can only use the -b:v setting. The crf is ignored. You can run a few test encodes and get an idea what video bitrate is "equivalent" to the CF you desire, then use that bit rate.

Enable QSV for FFmpeg with directshow input and JPEG image sequence output

I'm using FFmpeg with Directshow input. The output is a series of single JPEG images. FFmpeg itself maps the stream to mjpeg and uses image2 for the output.
Is it possible to increase performance by using the Intel QuickSync Video (QSV) hardware acceleration for this process? The FFmpeg QuickSync Wiki actually lists JPEG encoding since Braswell.
This is what I tried so far:
ffmpeg -init_hw_device qsv=hw -filter_hw_device hw -f dshow -video_size 3840x2160 -framerate 25 -i "video=My Webcam" -vf hwupload=extra_hw_frames=64,format=qsv -vcodec mjpeg_qsv "C:\out\%d.jpg"
The command works, images are generated - but the GPU load seems to be the same as without any qsv options..?
Thanks!
I compared it for a h264 encoded video. First with the QSV jpeg encoder:
ffmpeg -c:v h264_qsv -i myvideo.mkv -vcodec mjpeg_qsv images/%06d.jpg
and afterwards without mjpeg_qsv:
ffmpeg -c:v h264_qsv -i myvideo.mkv images/%06d.jpg
The example is minimalistic and can be improved in many ways. In the picture you can see the load of the GPU. In the red box with mjpeg_qsv and the blue box without mjpeg_qsv. The execution time was also better with mjpeg_qsv, speed=3.34x vs speed=1.84x. Since you are using your webcam as an source, your pipeline is limited by the frame rate of the live video. So, your hardware will only process 25 frames per second (-framerate 25). Depending on the resolution and your hardware, this might be an easy job for your GPU, in both cases. Also, make sure you look for the Intel GPU and not your Nvidia/AMD GPU. If you still have the impression that you can't see a performance gain, please let us know both of your commands for comparison.

What codec/format to use for fastest possible decoding?

I'm using an ffmpeg script (in Windows) that extracts all the keyframes from a video and pastes them into a folder. I've made sure that my drive speed, CPU, and RAM are not causing a bottleneck.
The quality of the video is actually not important at all in this case. I need to encode the video that the script extracts frames from so that it has the fastest possible decoding speed. File size and quality are not important, only read speed. The video does not have audio. What would work best for me?
If it matters, here's the script I'm working with:
ffmpeg -i input.mp4 -vf "select=eq(pict_type\,I)" -vsync 1 %%3d.bmp
Sorry if sound like I don't know what I'm talking about, this is not a topic I am super familiar with. I appreciate your help!
The below will be much faster for a codec like H.264
ffmpeg -discard nokey -i input.mp4 -vsync 0 %%3d.bmp
Your present approach decodes all frames and then the select filter gets to do gating, but the above command discards everything but keyframes at the demuxer level. It only works with MP4/MOV like containers.

using ffmpeg to create a wavefile image from opus

I have been trying to use ffmpeg to create a wavefile image from an opus file. so far i have found three different methods but cannot seem to determine which one is the best.
The end result is hopefully to have a sound-wave that is only approx. 55px in height. The image will become part of a css background-image.
Adapted from Generating a waveform using ffmpeg:
ffmpeg -i file.opus -filter_complex
"showwavespic,colorbalance=bs=0.5:gm=0.3:bh=-0.5,drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=1:color=black#0.5"
file.png
which produces this image:
Next, I found this one (and my favorite because of the simplicity):
ffmpeg -i test.opus -lavfi showwavespic=split_channels=1:s=1024x800 test.png
And here is what that one looks like:
Finally, this one from FFmpeg Wiki: Waveform, but it seems less efficient using a second utility (gnuplot) rather than just ffmpeg:
ffmpeg -i file.opus -ac 1 -filter:a
aresample=4000 -map 0:a -c:a pcm_s16le -f data - | \
gnuplot -e "set
terminal png size 525,050;set output
'file.png';unset key;unset tics;unset border; set
lmargin 0;set rmargin 0;set tmargin 0;set bmargin 0; plot '
Option two is my favorite, but i dont like the margins on the top and bottom of the waveforms.
Option three (using gnuplot) makes the best 'shaped' image for our needs, since the initial spike in sound seems to make the rest almost too small to use (lines tend to almost disappear) when the image is sized at only 50 pixels high.
Any suggestions how might best approach this? I really understand very little about any of the options I see, except of course for the size. Note too i have 10's of thousands to process, so naturally i want to make a wise choice at the very beginning.
Original and manipulated waveforms.
You can use the compand filter to adjust the dynamic range. drawbox is then used to make the horizontal line.
ffmpeg -i test.opus -filter_complex \
"compand=gain=-6,showwavespic=s=525x50, \
drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=1:color=white" \
-vframes 1 output.png
It won't be quite as accurate of a representation of your audio as the original waveform, but it may be an improvement visually; especially on such a wide scale.
Also see FFmpeg Wiki: Waveform.

Better vertical stabilization when simultaneously cropping to widescreen format

First of all: forgive me for maybe asking a stupid or somewhat uninformed question. I'm totally new to post processing video, stabilization, etc..
I'm shooting 1920x1080 compressed movie files with my Canon 5D2, and afterwards crop then to cinematic 1920x800 (2.4:1). (With Magic Lantern I use an overlay bitmap when shooting. And yes, I know that with magic lantern I can shoot RAW, but my cards as well as computer are not fast enough to deal with that much data.)
Before doing any production, I convert the big .MOV files to smaller ones, simultaneously stabilizing the video a bit, and cropping it to 1920x800. I do this with ffmpeg roughly as follows:
ffmpeg -i f.MOV -vf vidstabdetect -f null -
ffmpeg -i f.MOV -c:v libx264 -profile:v high -crf 18 -vf "vidstabtransform, crop=in_w:in_h-280" -c:a aac -strict experimental f2.mp4
However, the fact that a great deal of the vertical resolution is being cropped is not being used to be able to handle the stabilizing transforms better. Often, the image is stretched/skewed vertically, when this is not really needed given the crop used.
Is it possible in any way to use the crop befenificially in the stabilizing transforms?
An example is the frame below. Here, I would rather have that the image is not stretched vertically at all, and just get away with a slight static zoom (crop), because the horizontal black border is the only problem in this frame.
Better is use this command:
# to get the video fps
fps="$(ffmpeg -i $VarIN 2>&1 | sed -n 's/.*, \(.*\) fp.*/\1/p')"
transcode -J stabilize -i vidIn.mp4
transcode -J transform -i vidIn.mp4 -f $fps -y raw -o vidOut.avi

Resources