Skip to content

Instantly share code, notes, and snippets.

@h4k1m0u
Last active February 14, 2025 22:14
Show Gist options
  • Save h4k1m0u/1468d3aad151097a68a82b3914d30317 to your computer and use it in GitHub Desktop.
Save h4k1m0u/1468d3aad151097a68a82b3914d30317 to your computer and use it in GitHub Desktop.
hello-ffmpeg
cmake_minimum_required(VERSION 3.10)
project(VIDEO)
# autocomplete with clang in vim
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# debug with gdb
set(CMAKE_BUILD_TYPE Debug)
# ffmpeg libraries
find_library(AVFORMAT_LIBRARY avformat)
# copy video assets folder
file(COPY assets DESTINATION ${CMAKE_BINARY_DIR})
# main executable
add_executable(hello_ffmpeg src/hello_ffmpeg.c)
target_link_libraries(hello_ffmpeg ${AVFORMAT_LIBRARY})
#include <libavformat/avformat.h>
int main() {
// open mp4 file & read its header
AVFormatContext* context = NULL;
if (avformat_open_input(&context, "assets/video/bbb.mp4", NULL, NULL) != 0) {
printf("Failed to open stream\n");
}
// show video metadata
printf("Input format name: %s\n", context->iformat->name);
printf("Duration: %ld microseconds\n", context->duration);
printf("Number of streams: %d\n", context->nb_streams);
// free opened context
avformat_close_input(&context);
return 0;
}

Program

  • src/hello_ffmpeg.cpp: Read mp4 video and display its metadata.

Prerequisite

sudo apt install libavformat-dev

Notions about video processing

  • Demuxing: Split individual streams (video, audio, subtitles...) and send them to their respective decoders.
  • Muxing: Encapsulating multiple streams (video, audio...) into the same container (e.g. avi).
  • Bitrate: Number of bits processed / time unit (second). Affects the audio/video quality.
    • Video size = video bitrate * duration.
    • Audio size = audio bitrate * duration.
  • Framerate: Frames per second in the video (FPS).
  • Container: e.g. AVI, MP4
    • Audio stream: e.g. encoded by MP3 codec.
    • Video stream: e.g. encoded by DivX codec
  • Processing chain:
    • Video -> Demuxer -> Packets (for each stream)
    • Packets -> Decoder -> Frames (i.e. decoded data)
    • Frames -> Encoder -> Packets (i.e. encoded data)
    • Packets -> Muxer -> Video output

ffmpeg

  • libavformat: muxing, demuxing.
  • libavcodec: coding, decoding.

Assets

Tutorials for ffmpeg

Command-line tips

Extract a portion from a video

$ ffmpeg -i input.mp4 -ss 00:37:50 -t 00:00:20 -c copy output.mp4

Quicker with -c copy as the stream is copied as is without re-encoding.

Update: Even quicker if we put the -ss option before the input (to skip directly to the needed part):

$ ffmpeg -ss 00:53:25 -i "$p" -c copy subset.opus

List streams

$ ffprobe input.mp4

The following should show two streams at the very bottom:

  • Stream #0:0 for video stream
  • Stream #0:1 for audio stream

Extract audio/video

$ ffmpeg -i input.mp4 -map 0:1 -c copy audio.mp3
$ ffmpeg -i input.mp4 -map 0:0 -c copy video.mp4

Combine audio & video

$ ffmpeg -i video.mp4 -i audio.aac -c copy -map 0:0 -map 1:0 video-with-audio.mp4

Concat videos

The videos must've been encoded with the same codec.

$ vim files.txt
file 'video1.mp4'
file 'video2.mp4'
$ ffmpeg -f concat -i files.txt -c copy video-concat.mp4

Chain simple filters

Below a scaling-down is followed with a box blurring of 10px:

$ ffmpeg -i video-in.mp4 -filter:v scale=640:480,boxblur=10 video-out.mp4

Burn the subtitles

$ ffmpeg -i input.mp4 -ss 00:07:00 -t 00:00:05  -filter:v subtitles=input.srt output.mp4

Take a screenshot

$ ffmpeg -i input.mp4 -ss 00:00:02 -frames:v 1 screenshot.jpg

Convert audio format

Audio files downloaded from Youtube, usually in opus format, can be encoded as mp3 with a bitrate of 128K (# of bits processed each second) and a sample rate of 44100 (# of audio samples taken by second).

$ ffmpeg -i file.opus -b:a 128K -ar 44100 file.mp3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment