CLI tool
leandromoreira/ffmpeg-libav-tutorial avatar
leandromoreira/ffmpeg-libav-tutorial

leandromoreira/ffmpeg-libav-tutorial: learning libav in C by building a player

FFmpeg libav tutorial - learn how media works from basic to transmuxing, transcoding and more. Translations: 🇺🇸 🇨🇳 🇰🇷 🇪🇸 🇻🇳 🇧🇷 🇷🇺

11,051 stars1,012 forksCBSD-3-Clause

At a glance

What is it?
A C-language course that starts with frames and containers and ends with remuxing and transcoding code you compile against FFmpeg's libraries. It is aimed at developers who want to call libav from their own program, not at people who only need the ffmpeg binary.
Who is it for?
Adopt this tutorial if you are a developer who already writes C or can read it, and your goal is to call libavcodec and libavformat from your own program instead of shelling out to the ffmpeg binary. Do not adopt it if you only need to convert files: the ffmpeg command line covers remuxing, transrating and transsizing in one invocation, and the tutorial itself shows that path first.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 103 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the tutorial solves, and who it is written for

The README opens with a direct statement of motive: the author wanted a tutorial or book that would teach him to use FFmpeg as a library, found the older "How to write a video player in less than 1k lines" tutorial, and decided to write a replacement because that one was deprecated. That is the gap this repository fills. FFmpeg ships a command line binary and a set of C libraries, and most material on the internet covers only the binary. Calling libavcodec and libavformat from your own process is a different skill, with its own allocation, packet and frame lifecycle.

The audience is narrow on purpose. The code is C, and the README says so plainly while adding that the ideas transfer to other languages. It points at bindings such as PyAV for Python and go-libav for Go, and notes that a language without bindings can still reach libav through FFI, citing a Lua example. So the reader is someone comfortable reading C pointers and structs, or willing to translate them. If you want to transcode a file once and move on, this is the wrong entry point; the tutorial's own command line section already covers that case in a single command.

The teaching order: concepts, then the ffmpeg binary, then libav

The table of contents runs in three stages. First comes an intro that defines video as a series of frames at a rate, audio as a pressure wave converted through an ADC, a codec as something that compresses or decompresses digital audio and video, and a container as a single file holding all the streams plus synchronization and metadata. The storage math is the argument for codecs: a 1080x1920 video at 24 frames per second for 30 minutes, at 3 bytes per pixel, works out to roughly 250.28GB or 1.19 Gbps. That number is what makes the rest of the tutorial necessary.

Second comes the ffmpeg command line, where the README shows that converting an mp4 to an avi is remuxing, and notes that FFmpeg could also be transcoding in the same invocation. Third, and this is the bulk of the repository, comes the section titled "Learn FFmpeg libav the Hard Way", with chapters numbered 0 through 3. Chapter 0 is the hello world plus an architecture description. Chapter 1 is timing, or syncing audio and video. Chapter 2 is remuxing. Chapter 3 is transcoding. The repository layout matches: 0_hello_world.c, 2_remuxing.c, 3_transcoding.c, and a video_debugging.c with its header for the transcoding chapter.

Building the hello world example with the project's Docker image

There is no system package install documented. The Makefile runs everything through a Docker image, leandromoreira/ffmpeg-devel:4.4, mounting the current directory at /files. The repository also ships a Dockerfile that builds FFmpeg 4.4 from source on ubuntu:20.04 with a long list of codec libraries, but the Makefile targets use the published image rather than building it. The first target fetches the sample video:

bash
make fetch_small_bunny_video

That runs fetch_bbb_video.sh, which is the script that brings down small_bunny_1080p_60fps.mp4. Once the file is in place, the hello world target compiles and runs in one step:

bash
make run_hello

The compile step inside that target is the part worth reading, because it shows the link line you will need for your own code:

bash
gcc -L/opt/ffmpeg/lib -I/opt/ffmpeg/include/ /files/0_hello_world.c \
  -lavcodec -lavformat -lavfilter -lavdevice -lswresample -lswscale -lavutil \
  -o /files/build/hello

What you should see is the program printing information about the input file, since it is invoked as /files/build/hello /files/small_bunny_1080p_60fps.mp4. The same pattern repeats for remuxing and transcoding, with make run_remuxing_ts writing remuxed_small_bunny_1080p_60fps.ts and run_remuxing_fragmented_mp4 producing a fragmented mp4 by passing the extra argument fragmented.

What the four chapters actually teach, and what they skip

Chapter 0 is the entry point into libav's architecture, which the README describes as part of the chapter rather than as a separate document. Chapter 1 deals with timing, the problem of keeping audio and video aligned when they arrive as separate streams. Chapter 2 is remuxing, which in the tutorial's vocabulary means moving streams from one container to another without re-encoding, and the Makefile demonstrates it by writing both a .ts file and a fragmented mp4 from the same source. Chapter 3 is transcoding, the case where the codec itself changes, and it is the only chapter that pulls in video_debugging.c, compiled with -g -Wall. That debug helper suggests the author expects readers to hit real errors in this chapter rather than get it right on the first attempt.

What is not in the chapter list is as informative. There is no chapter on decoding to raw frames for display, no chapter on encoding from scratch, and no chapter on muxing a new stream you generated yourself. The tutorial is about moving and converting existing media, not about building a player end to end. The README's own framing supports that: it teaches what video, audio, codec and container are, then works up to transmuxing and transcoding.

Where this tutorial is the wrong tool

The most obvious failure mode is needing one conversion. The README's own command line section shows that ffmpeg -i input.mp4 output.avi performs a remux, and that the same binary can transcode. If that is your whole task, the tutorial's C chapters are overhead. You would be linking seven libraries to do what one process invocation does.

A second limit is API age. The Dockerfile pins FFMPEG_VERSION=4.4 and the Makefile pins the image tag leandromoreira/ffmpeg-devel:4.4. FFmpeg's libav API does change across major versions, and the tutorial does not document a migration path to 5.x or 6.x. If your production system already links a different FFmpeg major version, expect to reconcile deprecated calls yourself; the repository gives no guidance on that.

A third is the release history. The single listed release is 1.0.0 from 2020-10-08, described as adding the Chinese translation. That is a translation milestone, not an API refresh. The last push to the repository was on 2026-06-18, so the project has seen recent activity, but the chapter structure has been stable for years and nothing in the repository indicates the code has been retested against newer FFmpeg. Treat the code as a teaching reference to adapt, not a maintained library.

The alternative: calling the ffmpeg binary instead of libav

The real alternative is not another tutorial. It is not using libav at all, and driving the ffmpeg executable as a subprocess. The difference in approach is substantial. With the binary you get remuxing, transrating (changing bitrate) and transsizing (changing resolution) as documented command line operations, and you inherit FFmpeg's own maintenance of its API. With libav you take on the packet and frame lifecycle yourself, which is precisely the work the tutorial's chapters 0 through 3 walk through, and you gain the ability to process frames inside your own program without a subprocess boundary.

That trade is the decision this repository forces. If your pipeline needs to inspect, filter or generate frames in process, the subprocess route means parsing pipes and losing access to the structures, and libav is the answer. If your pipeline only needs files converted, the subprocess route is fewer moving parts. The tutorial's own structure concedes this by teaching the command line before the library.

Licence, translations and what adoption costs

The repository is BSD-3-Clause, shown in the README badge and present as a LICENSE file at the top level. That is permissive and imposes no copyleft on your own code, but it covers the tutorial's text and example code only. FFmpeg itself is a separate project with its own licensing, and the Dockerfile builds in a long list of third-party codec libraries including x264, x265, libvpx, opus, lame and fdk-aac. If you build that image or link those libraries into a product, their terms are yours to check; the BSD-3-Clause badge on this repository tells you nothing about them.

The upgrade cost is mostly yours. There is no versioned API contract here, no changelog beyond the one release, and no test suite listed in the repository layout. The Makefile is the closest thing to a reproducible build, and it depends on the leandromoreira/ffmpeg-devel:4.4 image remaining available. Translations exist for Simplified Chinese, Korean, Spanish, Vietnamese, Portuguese and Russian, so a reader who prefers one of those languages can follow the same chapters, but the code is the same C in every case.

Editorial conclusion

Adopt this tutorial if you are a developer who already writes C or can read it, and your goal is to call libavcodec and libavformat from your own program instead of shelling out to the ffmpeg binary. Do not adopt it if you only need to convert files: the ffmpeg command line covers remuxing, transrating and transsizing in one invocation, and the tutorial itself shows that path first. Before you start, check that the Docker image leandromoreira/ffmpeg-devel:4.4 referenced in the Makefile still pulls on your machine, and read the chapter list to confirm the API you need is one of the four covered.

Frequently asked questions

What is FFmpeg and how do you use it?

The tutorial describes FFmpeg as a complete, cross-platform solution to record, convert and stream audio and video, and notes that it ships a command line program called ffmpeg. Its command line section shows a basic use: ffmpeg -i input.mp4 output.avi, which the README calls a remux from one container to another. The rest of the repository teaches using FFmpeg as a library instead.

Can you provide a tutorial for using the FFmpeg library?

That is exactly what this repository is. It teaches the concepts first, then the ffmpeg command line, then a section called Learn FFmpeg libav the Hard Way with chapters on hello world, timing, remuxing and transcoding. The code is in C, and the README notes the ideas apply to other languages through bindings or FFI.

Is the FFmpeg library free?

This repository is licensed BSD-3-Clause, which covers the tutorial text and its example code. FFmpeg itself is a separate project, and the Dockerfile in this repository builds in many third-party codec libraries whose terms are not covered by that badge.

Is FFmpeg still being used?

The tutorial's introduction notes that you likely already use FFmpeg directly or indirectly and points to Chrome as an example. It also says that FFmpeg is worth studying, comparing internet video streaming to traditional TV. The repository itself does not report usage numbers.

Official sources

  1. leandromoreira/ffmpeg-libav-tutorial on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/leandromoreira-ffmpeg-libav-tutorial.svg)](https://hysenlabs.com/projects/leandromoreira-ffmpeg-libav-tutorial)