All multimedia apps (FFMPEG, ImageMagick, AV1 encoders ect...) in a docker container.
- FFMPEG
- Handbrake cli
- ImageMagick
Software | Minimum | Recommended |
---|---|---|
Linux | Any | Any |
Docker | 19.x | 20.x |
Make | 4.x | 4.x |
Hardware | Minimum | Recommended |
---|---|---|
CPU | 2c/2t | 6c/12t |
Instruction set (x86) | x86-64-v2 | x86-64-v3 |
Instruction set (ARM) | armv8 | armv8 |
RAM | 8 GB | 32 GB |
GPU | - | Hardware enc/dec |
Disk space | 4 GB | 16 GB |
Internet | 10 Mbps | 100 Mbps |
Clone this repository
git clone --recurse-submodules https://github.com/bensuperpc/docker-multimedia.git
make archlinux
Test the container:
make archlinux.test
Now you can start the container, it will mount the current directory in the container.
./docker-multimedia.sh <command>
make update
Option | default | Example | Description |
---|---|---|---|
-vf | - | -vf scale=1920:-1 | Downscale the video to 1080p |
-g | ? | -g 60 | Set the keyframe interval of x frames, lower value increase quality but increase file size |
-pix_fmt | Depends on source | -pix_fmt yuv420p | Set the pixel format, yuv420p for 8-bit, yuv420p10le for 10-bit ect... |
-crf | - | - | Constant Rate Factor, options depend on the encoder |
-preset | - | - | Set the encoding speed, options depend on the encoder |
-tune | - | - | Set the encoding tune, options depend on the encoder |
-c:v | - | -c:v libx265 | Set the video codec, options depend on installed codecs |
-c:a | - | -c:a copy | Set the audio codec, options depend on installed codecs |
-c:s | - | -c:s copy | Set the subtitle codec, options depend on installed codecs |
-threads | 0 | -threads 8 | Set the number of threads, 0 for auto |
-map | - | -map 0 | Map the input stream to the output |
-map_metadata | - | -map_metadata 0 | Map the metadata to the output |
-map_chapters | - | -map_chapters 0 | Map the chapters to the output |
-fps_mode | auto | -fps_mode passthrough | Set the frame rate mode, passthrough, cfr, vfr, auto |
-loglevel | - | -loglevel error | Set the log level, error, warning, info, verbose, debug, trace |
-hide_banner | - | -hide_banner | Hide the banner |
-y | - | -y | Overwrite output files without asking |
This table shows the most common options for SVT-AV1, like the preset, crf, and svtav1-params.
For svtav1-params each option is separated by a colon :
, option and value are separated by =
, like tune=0:enable-qm=1:qm-min=0
.
Option | default | Min/Max | Example | Description |
---|---|---|---|---|
-preset | 4 | -preset 4 | 0-12 | 0 for slowest, 12 for fastest encoding |
-crf | 18 | -crf 30 | 0-63 | Constant Rate Factor, lower value increase quality |
-svtav1-params | - | - | -svtav1-params tune=0:enable-qm=1 | SVT-AV1 specific options |
tune | 1 | 0-1 | -svtav1-params tune=0 | 0 for subjective quality, 1 for objective quality (PSNR) |
enable-qm | 0 | 0-1 | -svtav1-params enable-qm=1 | Enable quantization matrices |
qm-min | 8 | 0-15 | -svtav1-params qm-min=0 | Minimum quantization matrix |
qm-max | 15 | 0-15 | -svtav1-params qm-max=10 | Maximum quantization matrix |
enable-overlays | 0 | 0-1 | -svtav1-params enable-overlays=1 | Enable overlays |
film-grain | 0 | 0-12 | -svtav1-params film-grain=8 | Add film grain to the video |
More information about the options can be found in the SVT-AV1 documentation
Example of encoding CRF for very high quality (Maybe little overkill, preset 4 and crf 20 is a good start for 1080p).
./docker-multimedia.sh ffmpeg -i input.mkv -c:v libsvtav1 -preset 2 -crf 14 -svtav1-params tune=0:enable-qm=1:qm-min=0:qm-max=8 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
- -preset 1: i recommend to use 4-6 for good quality and speed, 3 or lower for better quality but it really slow (~2x slower per lower step, for minimal gain).
- -crf 14: CRF 20-24 is a good start, 14 for very high quality bit bigger file size.
- tune=0: Enable subjective quality, 1 for objective quality (PSNR).
- enable-qm=1: Enable quantization matrices.
- qm-min=0: Minimum quantization matrix, reduce it for lower compression in certain zones, the 8 default is little too high, 0-4 is a good start.
- qm-max=8: Maximum quantization matrix, increase it for higher compression in certain zones, the 15 default is little too high, 8-12 is a good start.
With AV1AN, it usefull if you have move than 16 threads, SVT-AV1 is not well optimized for over 16 threads, AV11AN encode the video in parallel per scene.
./docker-multimedia.sh av1an -i input.mkv --encoder svt-av1 --video-params "--rc 0 --crf 16 --preset 1 --tune 0 --enable-qm=1 --qm-min=0 --qm-max=8" --audio-params "-c:a copy" -o temp_output.mkv
Copy metadata and chapters:
ffmpeg -i temp_output.mkv -i input.mkv -map 0 -map_metadata 1 -map_chapters 1 -c copy output.mkv
Optional for AV1AN:
- Add
--video-filter "scale=1920:-1"
to downscale the video to 1080p - Add
--keyint 60
in video-params to set the keyframe interval to 60 frames (every 1 seconds at 60fps), lower value increase quality but increase file size
./docker-multimedia.sh ffmpeg -i input.mkv -c:v libaom-av1 -crf 18 -cpu-used 3 -row-mt 1 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -y -c:v librav1e -crf 18 -speed 3 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -y -c:v libx265 -crf 18 -preset slower -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -y -c:v libx265 -preset slow -vf scale=1280:-1 -b:v 2000k -minrate 500k -maxrate 6000k -bufsize 12000k -pass 1 -an -f null /dev/null && ffmpeg -i input.mkv -preset slow -vf scale=1280:-1 -c:v libx265 -b:v 2000k -minrate 500k -maxrate 6000k -bufsize 12000k -pass 2 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -c:v libx264 -crf 26 -preset slow -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -c:v ffv1 -level 3 -coder 1 -context 1 -g 1 -slices 4 -slicecrc 1 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
./docker-multimedia.sh ffmpeg -i input.mkv -c:v ffv1 -level 3 -coder 1 -context 1 -g 1 -slices 4 -slicecrc 1 -pass 1 -an -f null /dev/null && ffmpeg -i input.mkv -c:v ffv1 -level 3 -coder 1 -context 1 -g 1 -slices 4 -slicecrc 1 -pass 2 -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mkv
SSIM Y: For luma (Y) channel, 0-1, 1 is perfect match SSIM U: For chrominance (U) channel, 0-1, 1 is perfect match SSIM V: For chrominance (V) channel, 0-1, 1 is perfect match SSIM All: Average of YUV, 0-1, 1 is perfect match
./docker-multimedia.sh ffmpeg -i output.mkv -i input.mkv -lavfi ssim -f null –
PSNR Y: For luma (Y) channel, in dB higher is better PSNR U: For chrominance (U) channel, in dB higher is better PSNR V: For chrominance (V) channel, in dB higher is better PSNR All: Average of YUV, in dB higher is better
./docker-multimedia.sh ffmpeg -i output.mkv -i input.mkv -lavfi psnr -f null –
VMAF score, higher is better
./docker-multimedia.sh ffmpeg -i output.mkv -i input.mkv -lavfi libvmaf -f null –
Output into a json file
./docker-multimedia.sh ffmpeg -i video1.mp4 -i video2.mp4 -lavfi libvmaf="log_path=vmaf.json:log_fmt=json" -f null -
Extract from 125s to 200s
./docker-multimedia.sh ffmpeg -i input.mp4 -ss 125 -t 75 -copyts -map_metadata 0 -vcodec copy -acodec copy out.mkv
Extract from 125s to 150s
./docker-multimedia.sh ffmpeg -i input.mp4 -ss 125 -to 150 -c copy -copyts -map_metadata 0 -vcodec copy -acodec copy out.mkv
Import watermark at 10:10 from the top left corner
./docker-multimedia.sh ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mp4
Speed up the video by 2x
./docker-multimedia.sh ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" -af "atempo=2.0" -map_metadata 0 output.mp4
Change the video frame rate to 30fps (2x slower if the original is 60fps)
./docker-multimedia.sh ffmpeg -i input.mp4 -filter:v fps=fps=30 -map_metadata 0 output.mp4
./docker-multimedia.sh ffmpeg -i input.mp4 -vf "fps=24,scale=480:-1:flags=lanczos" -c:v gif -map_metadata 0 output.gif
ffplay -i input.mp4 -vf "curves=vintage,noise=alls=30:allf=t+u,hue=s=0.7,eq=contrast=0.85:brightness=-0.1:saturation=0.7,gblur=sigma=1.5,colorbalance=rm=0.2:gm=0.1:bm=-0.2,vignette"
- curves=vintage: Add a vintage look
- noise=alls=30:allf=t+u: Add noise
- hue=s=0.7: Reduces saturation
- eq=contrast=0.85:brightness=-0.01:saturation=0.7: Adjust contrast, brightness and saturation
- gblur=sigma=1.5: Add a gaussian blur
- colorbalance=rm=0.2:gm=0.1:bm=-0.2: Adjust color balance to sepia tone
- vignette: Add a vignette
./docker-multimedia.sh find . -name "*.png" | parallel -eta cwebp -metadata all -lossless -exact -z 9 "{}" -o "{.}.webp" && find . -name "*.png" -exec sh -c 'touch -r "${0%.*}.png" "${0%.*}.webp"' "{}" ';'
./docker-multimedia.sh compare -metric AE input1.png input2.webp null:
Or with ImageMagick
./docker-multimedia.sh magick input1.png ppm:- | magick input2.webp ppm:- | diff -q - <(magick input2.webp ppm:-)
You can generate a spectrogram with sox, for example with a flac file to detect "fake" flac files.
./docker-multimedia.sh sox input_audio.flac -n spectrogram -o output_spectrogram.png
Add -t flac
if the input file is not recognized as flac.
./docker-multimedia.sh ffmpeg -i input.mp4 -af "volume=2.0" -c:v copy -c:a copy -c:s copy -map 0 -map_metadata 0 -map_chapters 0 output.mp4
Audio lib | Max bitrate | Extension |
---|---|---|
libmp3lame | 320kbps | mp3 |
aac | 250kbps | m4a |
libopus | 250kbps | opus |
flac | lossless | flac |
pcm_s16le | 16bit | wav |
Convert audio to mp3
./docker-multimedia.sh ffmpeg -i input.flac -c:a libmp3lame -b:a 320k output.mp3
Convert audio to lossy or "fake" flac
./docker-multimedia.sh ffmpeg -i output.mp3 output.flac
Remove noise from audio
./docker-multimedia.sh ffmpeg -i input.mp3 -af "highpass=f=200, lowpass=f=3000" output.mp3
Convert to compatible audio format for garry's mod
./docker-multimedia.sh ffmpeg -i input.mp3 -c:a pcm_s16le -b:a 128k -ar 44100 -ac 2 output.wav
./docker-multimedia.sh ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
Download audio from youtube video without re-encoding:
./docker-multimedia.sh yt-dlp -f bestaudio --extract-audio --embed-thumbnail --embed-metadata --embed-chapters --output "%(title)s.%(ext)s" "https://www.youtube.com/watch?v=video_playlist_id"
Download video from youtube video without re-encoding:
./docker-multimedia.sh yt-dlp -f "bestvideo+(251/mergeall[format_id~=251-])" --audio-multistreams --sub-langs "all,-live_chat" --embed-chapters --embed-metadata --merge-output-format mkv --output "%(title)s.%(ext)s" "https://www.youtube.com/watch?v=video_id"