FFmpeg is a powerful open-source library for processing multimedia files like videos and audios. It provides various tools and APIs for tasks like format conversion, resizing, editing, and more. In this article, we will see how to use ffmpeg to transcode a video file from one format to another.
To follow along, you will need:
At a high level, transcoding a video involves these steps:
Let’s look at the code to implement these steps.
We begin by including the required FFmpeg headers and registering all the codecs and formats:
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
// other headers
}
av_register_all();
Next, we open the input video file using avformat_open_input()
and get the input format context:
AVFormatContext *input_format_ctx = nullptr;
if (avformat_open_input(&input_format_ctx, input_file, nullptr, nullptr) < 0) {
// error handling
}
We find the index of the video stream inside the input file:
int video_stream_idx = -1;
for (int i = 0; i < input_format_ctx->nb_streams; i++) {
if (input_format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_idx = i;
break;
}
}
And get the codec context and parameters for decoding:
AVCodecParameters *codecpar =
input_format_ctx->streams[video_stream_idx]->codecpar;
AVCodec *decoder = avcodec_find_decoder(codecpar->codec_id);
AVCodecContext *codec_ctx = avcodec_alloc_context3(decoder);
avcodec_parameters_to_context(codec_ctx, codecpar);
We now setup the output format context with the filename, codec and other parameters:
AVFormatContext *output_format_ctx = nullptr;
avformat_alloc_output_context2(&output_format_ctx, nullptr,
nullptr, output_file);
AVStream *out_stream = avformat_new_stream(output_format_ctx,
codec);
avcodec_parameters_copy(out_stream->codecpar, codecpar);
And open the output file for writing:
if (!(output_format_ctx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&output_format_ctx->pb, output_file,
AVIO_FLAG_WRITE) < 0) {
// error handling
}
}
Now we can read frames from input, decode them using avcodec_send_packet()
and avcodec_receive_frame()
, do processing if needed, and finally encode the frames with the output codec and write them to output file.
while (av_read_frame(input_format_ctx, &packet) >= 0) {
avcodec_send_packet(codec_ctx, &packet);
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
// decoding successful
// process frame if needed
avcodec_send_frame(output_codec_ctx, frame);
avcodec_receive_packet(output_codec_ctx, &opacket);
av_interleaved_write_frame(output_format_ctx, &opacket);
}
}
Finally, we free the allocated resources and close the files.
This covers the basic transcoding workflow with FFmpeg. Several additional steps may be needed for robust encoding, like handling subtitles, metadata etc. But this gives an overview of the process.