FFmpegでのビデオデコード関連知識の紹介

1 はじめに

FFmpeg は、非常に人気のあるオープン ソースのクロスプラットフォーム マルチメディア ソリューションです。さまざまなオーディオおよびビデオ形式のエンコード、デコード、変換、およびストリーミングに使用できます。この記事では、FFmpeg でのビデオ デコードに関する知識を紹介します。

2. ビデオデコーダー

FFmpeg のビデオ デコーダは、H.264、MPEG-4、AVC、VP9 など、さまざまなビデオ エンコーディング フォーマットをサポートしています。

2.1 FFmpeg ビデオデコーダー

FFmpeg ビデオ デコーダーは、次のように avcodec_find_decoder() 関数を使用して見つけることができます。

AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
    fprintf(stderr, "无法找到解码器\n");
    return -1;
}

上記のコードは、AV_CODEC_ID_H264 パラメーターを使用して H.264 デコーダーを見つけます。指定されたデコーダーが見つからない場合は NULL を返します。

2.2 ビデオパケットのデコード

ビデオ デコーディング プロセスでは、ビデオ データ ストリームを読み取り、複数の圧縮フレームに分割し、各圧縮フレームを元のビデオ フレームにデコードする必要があります。ビデオ データ ストリームは、次のように av_read_frame() 関数を使用して読み取ることができます。

AVPacket packet;
​
while (av_read_frame(pFormatCtx, &packet) >= 0) {
​
    // 如果是视频流
    if (packet.stream_index == videoStreamIndex) {
​
        // 发送数据包给解码器
        if (avcodec_send_packet(pCodecCtx, &packet) != 0) {
            fprintf(stderr, "无法向解码器发送数据包\n");
            break;
        }
​
        // 解码帧数据
        while (avcodec_receive_frame(pCodecCtx, pFrame) == 0) {
            // 处理解码后的视频帧
            // ...
        }
    }
​
    av_packet_unref(&packet);
}

上記のコードは、av_read_frame() 関数を使用して、ビデオ データ ストリーム内の各データ パケットを読み取り、それがビデオ ストリームであるかどうかを判断します。ビデオ ストリームの場合は、avcodec_send_packet() を使用してデータ パケットをデコーダに送信し、デコードしてから、avcodec_receive_frame() 関数を使用して、デコードされたビデオ フレームを受信します。

2.3 ビデオフレームフォーマット変換

デコード中に、ビデオ フレームをさまざまな形式にデコードするオプションがあります。ビデオ フレームは、SwsContext 構造体と sws_scale() 関数を使用して、目的の出力形式に変換できます。例えば:

struct SwsContext *pSwsContext = sws_getContext(
    pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
    output_width, output_height, AV_PIX_FMT_RGB24,
    SWS_BILINEAR, NULL, NULL, NULL);
​
sws_scale(pSwsContext, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, &buffer, NULL);

上記のコードは、変換コンテキストを作成し、sws_scale() 関数を使用してソース ビデオ フレームを RGB 形式に変換し、バッファに格納します。

2.4 リソースのクリーンアップ

ビデオのデコードが完了したら、メモリ リークを回避するために、使用されたリソースをクリーンアップする必要があります。av_free()、av_frame_free()、avcodec_close() などの関数を使用して、対応するリソースを解放できます。例えば:

av_free(buffer);
av_frame_free(&pFrame);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);

上記は、いくつかの基本的な FFmpeg ビデオ デコーダ関連の知識とコード例です. 特定の実装は、さまざまなアプリケーション シナリオにより異なる場合があります.

3. オーディオとビデオのデコード

FFmpeg は、オーディオとビデオを同時にデコードできます。オーディオとビデオのデコードには、avcodec_decode_audio4() 関数や avcodec_decode_video2() 関数などのさまざまな関数を使用できます。

オーディオとビデオのデコードは、FFmpeg の基本機能の 1 つです。

3.1 オーディオのデコード

オーディオをデコードするには、オーディオ ファイルを開き、オーディオ ストリームを取得してデコードする必要があります。

オーディオをデコードするためのコード サンプルを次に示します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
​
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/audio_fifo.h>
#include <libavutil/frame.h>
​
int main(int argc, char** argv) {
    // 打开输入音频文件
    AVFormatContext* format_ctx = NULL;
    if (avformat_open_input(&format_ctx, "input.mp3", NULL, NULL) != 0) {
        fprintf(stderr, "Failed to open input file\n");
        return -1;
    }
​
    // 获取音频流信息
    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        fprintf(stderr, "Failed to find stream information\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 查找第一个音频流
    int audio_stream_idx = -1;
    for (int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audio_stream_idx = i;
            break;
        }
    }
    if (audio_stream_idx == -1) {
        fprintf(stderr, "No audio stream found\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 获取音频解码器
    AVCodec* codec = avcodec_find_decoder(format_ctx->streams[audio_stream_idx]->codecpar->codec_id);
    if (codec == NULL) {
        fprintf(stderr, "Unsupported codec\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 打开音频解码器
    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[audio_stream_idx]->codecpar) < 0) {
        fprintf(stderr, "Failed to copy codec parameters to decoder context\n");
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Failed to open codec\n");
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 初始化音频缓冲区和FIFO
    int frame_size = codec_ctx->frame_size;
    AVAudioFifo* fifo = av_audio_fifo_alloc(codec_ctx->sample_fmt, codec_ctx->channels, frame_size);
    if (fifo == NULL) {
        fprintf(stderr, "Failed to allocate audio FIFO\n");
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
    uint8_t** buffer = NULL;
    if (av_samples_alloc_array_and_samples(&buffer, NULL, codec_ctx->channels, frame_size, codec_ctx->sample_fmt, 0) < 0) {
        fprintf(stderr, "Failed to allocate audio buffer\n");
        av_audio_fifo_free(fifo);
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 解码音频流
    AVPacket packet;
    av_init_packet(&packet);
    while (av_read_frame(format_ctx, &packet) == 0) {
        if (packet.stream_index == audio_stream_idx) {
            int ret = avcodec_send_packet(codec_ctx, &packet);
            if (ret < 0) {
                fprintf(stderr, "Error sending a packet for decoding\n");
                break;
            }
            while (ret >= 0) {
                AVFrame* frame = av_frame_alloc();
                ret = avcodec_receive_frame(codec_ctx, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    av_frame_free(&frame);
                    break;
                } else if (ret < 0) {
                    fprintf(stderr, "Error during decoding\n");
                    av_frame_free(&frame);
                    break;
                }
                int samples = av_samples_get_buffer_size(NULL, codec_ctx->channels, frame->nb_samples, codec_ctx->sample_fmt, 0);
                if (samples <= 0) {
                    av_frame_free(&frame);
                    continue;
                }
                memcpy(buffer[0], frame->data[0], samples);
                if (codec_ctx->channels > 1) {
                    memcpy(buffer[1], frame->data[1], samples / 2);
                }
                av_audio_fifo_write(fifo, (void**)buffer, frame->nb_samples);
                av_frame_free(&frame);
            }
        }
        av_packet_unref(&packet);
    }
    av_packet_unref(&packet);
​
    // 关闭音频解码器和输入文件,释放缓冲区和FIFO
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
    av_freep(&buffer[0]);
    av_freep(&buffer);
    av_audio_fifo_free(fifo);
​
    return 0;
}

3.2 ビデオのデコード

ビデオをデコードするには、ビデオ ファイルを開き、ビデオ ストリームを取得してデコードする必要があります。以下は、ビデオをデコードするためのコード サンプルです。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
​
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
​
int main(int argc, char** argv) {
    // 打开输入视频文件
    AVFormatContext* format_ctx = NULL;
    if (avformat_open_input(&format_ctx, "input.mp4", NULL, NULL) != 0) {
        fprintf(stderr, "Failed to open input file\n");
        return -1;
    }
​
    // 获取视频流信息
    if (avformat_find_stream_info(format_ctx, NULL) < 0) {
        fprintf(stderr, "Failed to find stream information\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 查找第一个视频流
    int video_stream_idx = -1;
    for (int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_idx = i;
            break;
        }
    }
    if (video_stream_idx == -1) {
        fprintf(stderr, "No video stream found\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 获取视频解码器
    AVCodec* codec = avcodec_find_decoder(format_ctx->streams[video_stream_idx]->codecpar->codec_id);
    if (codec == NULL) {
        fprintf(stderr, "Unsupported codec\n");
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 打开视频解码器
    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[video_stream_idx]->codecpar) < 0) {
        fprintf(stderr, "Failed to copy codec parameters to decoder context\n");
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Failed to open codec\n");
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 初始化视频缓冲区和转换器
    AVFrame* frame = av_frame_alloc();
    AVFrame* rgb_frame = av_frame_alloc();
    uint8_t* buffer = NULL;
    int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
    if (num_bytes <= 0) {
        fprintf(stderr, "Failed to get image buffer size\n");
        av_frame_free(&rgb_frame);
        av_frame_free(&frame);
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
    buffer = (uint8_t*)av_malloc(num_bytes * sizeof(uint8_t));
    if (buffer == NULL) {
        fprintf(stderr, "Failed to allocate image buffer\n");
        av_frame_free(&rgb_frame);
        av_frame_free(&frame);
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
    av_image_fill_arrays(rgb_frame->data, rgb_frame->linesize, buffer, AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
    struct SwsContext* sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, NULL, NULL, NULL);
    if (sws_ctx == NULL) {
        fprintf(stderr, "Failed to initialize color conversion context\n");
        av_freep(&buffer);
        av_frame_free(&rgb_frame);
        av_frame_free(&frame);
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        return -1;
    }
​
    // 解码视频流
    AVPacket packet;
    av_init_packet(&packet);
    while (av_read_frame(format_ctx, &packet) == 0) {
        if (packet.stream_index == video_stream_idx) {
            int ret = avcodec_send_packet(codec_ctx, &packet);
            if (ret < 0) {
                fprintf(stderr, "Error sending a packet for decoding\n");
                break;
            }
            while (ret >= 0) {
                ret = avcodec_receive_frame(codec_ctx, frame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                } else if (ret < 0) {
                    fprintf(stderr, "Error during decoding\n");
                    break;
                }
                sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height, rgb_frame->data, rgb_frame->linesize);
                // 在此处可以将RGB图像显示或保存到文件中
            }
        }
        av_packet_unref(&packet);
    }
    av_packet_unref(&packet);
​
    // 关闭视频解码器和输入文件,释放缓冲区和转换器
    sws_freeContext(sws_ctx);
    av_freep(&buffer);
    av_frame_free(&rgb_frame);
    av_frame_free(&frame);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
​
    return 0;
}

上記のコード サンプルは、FFmpeg を使用してオーディオとビデオをデコードする方法を示しています。実際のアプリケーションでは、特定の要件に従って、デコードされたオーディオとビデオを処理、保存、または再生することも必要です。

4. フレームレート制御

フレーム レート (フレーム レート) は、1 秒あたりに再生されるフレーム数を指し、通常は FPS (1 秒あたりのフレーム数) で表されます。ビデオの品質と流暢さはフレーム レートに大きく関係しており、一般的に、フレーム レートが高いほどビデオは滑らかになりますが、より多くのストレージ スペースとコンピューティング リソースが必要になります。

【学習アドレス】:FFmpeg/WebRTC/RTMP/NDK/Androidの音声・動画ストリーミングメディアの高度な開発

[記事の特典]: より多くのオーディオおよびビデオ学習パッケージ、Dachang インタビューの質問、テクニカル ビデオ、学習ロードマップを無料で受け取ることができます (C/C++、Linux、FFmpeg webRTC rtmp hls rtsp ffplay srs など) 1079654574 をクリックして参加ます受け取るグループ〜

以下に、一般的なフレーム レート制御方法をいくつか示します。

4.1-rオプション

これは最も単純なフレーム レート制御方法です。このオプションを使用して、出力ビデオ ストリームのフレーム レートを指定します。

たとえば、次のコマンドは、入力ビデオのフレーム レートを 25 fps に設定し、それを出力ファイル output.mp4 に書き込みます。

ffmpeg -i input.mp4 -r 25 output.mp4

4.2setptsフィルター

フィルターを使用して、setptsビデオ フレーム間の時間間隔を調整します。

たとえば、次のコマンドは、ビデオのフレーム レートを 60 fps に上げて、output.mp4 に出力します。

ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" -r 60 output.mp4

ここでは、各ビデオ フレームの表示時間を半分にすることで、ビデオ フレーム レートを上げています。

4.3fpsフィルター

フィルタを使用してfps、ビデオ ストリームから特定のフレームを抽出し、指定したレートで新しいビデオ ストリームを生成できます。

たとえば、次のコマンドは生のビデオを 10fps の gif 画像に変換します。

ffmpeg -i input.mp4 -vf fps=10 output.gif

4.4フィルターselectとの組み合わせsetpts

selectフィルターとフィルターを組み合わせて使用​​すると、setpts指定した時間間隔でビデオ フレームを画像にキャプチャし、それらを同じフレーム レートに保つことができます。

たとえば、次のコマンドは、入力ビデオから 10 秒ごとに画像をキャプチャし、output_%03d.jpg として保存します。

ffmpeg -i input.mp4 -vf "select=not(mod(n\,300)),setpts=N/FRAME_RATE/TB" output_%03d.jpg

これは、mod(n\,300)300 フレームごとに 1 フレームだけが選択され、setpts=N/FRAME_RATE/TB各フレームの表示時間がフレーム レートに従って再計算されることを意味します。

一般に、FFmpeg は、より洗練されたビデオ処理効果を実現するために、さまざまなシナリオに従って柔軟に使用できる豊富なフレーム レート制御機能を提供します。

4.5 フレームレート制御の実現

FFmpeg では、入力ビデオの PTS (プレゼンテーション タイム スタンプ、表示タイム スタンプ) と DTS (デコード タイム スタンプ、デコード タイム スタンプ) を調整することで、フレーム レート コントロールを実装します。たとえば、次のようになります。

4.5.1 出力ビデオのフレームレートを指定する

FPS フィルターを使用すると、出力ビデオのフレーム レートを指定できます。次に例を示します。

ffmpeg -i input.mp4 -c:v libx264 -filter:v fps=30 output.mp4

このコマンドは、input.mp4 を H.264 エンコード形式に変換し、出力ビデオ フレーム レートを 30 に設定します。

4.5.2 入力ビデオのフレームレートを変更する

元のビデオのフレーム レートが高すぎるか低すぎる場合は、現在のシーンに合わせて変更する必要があります。setpts フィルターを使用して入力ビデオの PTS を変更し、それによって次のようにフレーム レートを変更します。

# 将25fps的视频转换为30fps
ffmpeg -i input.mp4 -filter:v "setpts=1.25*PTS" output.mp4
​
# 将60fps的视频转换为30fps
ffmpeg -i input.mp4 -filter:v "setpts=2.0*PTS" output.mp4

このコマンドは、フレーム レートを変更するという目的を達成するために、input.mp4 の各フレームの表示タイムスタンプを 2 倍または半分にします。

フレームレートを変更すると、ビデオの歪みや歪みが発生する可能性があるため、注意して使用する必要があります。

5. デコーダ出力フォーマット

FFmpeg では、デコーダーは、オーディオおよびビデオ データを圧縮形式から元の形式にデコードするコンポーネントの 1 つです。

FFmpegデコーダーの出力フォーマットは入力フォーマットに関連しており、異なる入力フォーマットは異なるデコーダーに対応し、異なるデコーダーの出力フォーマットもわずかに異なります。一般的に言えば、FFmpeg デコーダーは、次の一般的に使用されるビデオおよびオーディオ形式を出力できます。

5.1 ビデオフォーマット

5.1.1 YUV フォーマット

YUV は色空間であり、一般的なビデオ形式です。YUV 画像は、輝度 (Y) とクロミナンス (U、V) の 3 つのコンポーネントで構成されます。このうち、Y は明度、U と V は色度を表します。ビデオのエンコードと処理では、YUV420P、YUV422P、YUV444P などのサブフォーマットがよく使用されます。

ビデオを YUV 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp4 -pix_fmt yuv420p output.yuv

このコマンドは、input.mp4 ファイルを YUV420P 形式に変換し、output.yuv ファイルに保存します。

5.1.2 RGB フォーマット

RGB は一般的な色空間であり、一般的なビデオ形式です。RGB 画像は、赤、緑、青の 3 つの基本色で構成されます。ビデオ処理では、RGB24、RGBA などのサブフォーマットがよく使用されます。

ビデオを RGB 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp4 -pix_fmt rgb24 output.rgb

このコマンドは、input.mp4 ファイルを RGB24 形式に変換し、output.rgb ファイルに保存します。

5.1.3 H.264/H.265 フォーマット

H.264/H.265 は一般的なビデオ圧縮形式で、高解像度を確保しながらビデオ ファイルのサイズを大幅に縮小できます。FFmpeg では、エンコーダーとパラメーターを指定することで、ビデオを H.264/H.265 形式にエンコードできます。

ビデオを H.264 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp4 -c:v libx264 output.mp4

このコマンドは、input.mp4 ファイルを H.264 エンコード形式に変換し、output.mp4 ファイルに保存します。

ビデオを H.265 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp4 -c:v libx265 output.mp4

このコマンドは、input.mp4 ファイルを H.265 エンコード形式に変換し、output.mp4 ファイルに保存します。

異なるビデオ形式は、出力品質、ファイルサイズ、デコード速度などの異なる特性に対応していることに注意してください。これらは、使用時に実際のニーズに応じて選択および調整する必要があります。

5.2 オーディオフォーマット

5.2.1 PCM フォーマット

PCM は可逆圧縮形式で、音質は非常に優れていますが、ファイル サイズが大きくなります。FFmpeg では、オーディオ ファイルを PCM 形式に変換したり、PCM 形式から他の形式に変換したりできます。

オーディオを PCM 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp3 -acodec pcm_s16le output.wav

このコマンドは、input.mp3 ファイルを PCM 形式に変換し、output.wav ファイルに保存します。

PCM 形式を他の形式に変換するには、次のコマンドを使用できます。

ffmpeg -f s16le -ar 44100 -ac 2 -i input.pcm -acodec libmp3lame output.mp3

このコマンドは、input.pcm ファイルを MP3 形式に変換し、output.mp3 ファイルに保存します。

5.2.2 MP3 形式

MP3 は非可逆圧縮形式で、オーディオ ファイルのサイズを効果的に縮小できますが、音質がいくらか失われます。FFmpeg では、オーディオ ファイルを MP3 形式に変換したり、MP3 形式から他の形式に変換したりできます。

オーディオを MP3 形式に変換するには、次のコマンドを使用できます。

将MP3格式转换为其他格式可以使用如下命令:

ffmpeg -i input.mp3 -acodec pcm_s16le output.wav

このコマンドは、input.wav ファイルを MP3 形式に変換し、output.mp3 ファイルに保存します。

MP3 形式を他の形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.mp3 -acodec pcm_s16le output.wav

このコマンドは、input.mp3 ファイルを PCM 形式に変換し、output.wav ファイルに保存します。

5.2.3 AAC フォーマット

AAC は一般的な非可逆圧縮オーディオ形式で、MP3 よりも高度で、より高い音質圧縮率を実現できます。FFmpeg では、オーディオ ファイルを AAC 形式に変換したり、AAC 形式から他の形式に変換したりできます。

オーディオを AAC 形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.wav -c:a libfdk_aac -b:a 128k output.aac

このコマンドは、input.wav ファイルを AAC 形式に変換し、output.aac ファイルに保存します。

AAC 形式を他の形式に変換するには、次のコマンドを使用できます。

ffmpeg -i input.m4a -acodec pcm_s16le output.wav

このコマンドは、input.m4a ファイルを PCM 形式に変換し、output.wav ファイルに保存します。

異なるオーディオ形式は、異なる出力品質、ファイルサイズ、デコード速度などに対応しており、使用時に実際のニーズに応じて選択および調整する必要があることに注意してください。

6. ビデオのエンコード形式

FFmpeg では、ビデオ エンコーダーは生のビデオ データ (YUV や RGB など) をさまざまなビデオ エンコード形式に圧縮するコンポーネントの 1 つです。一般的に使用されるビデオ エンコーディング形式の一部を以下に紹介します。

6.1 H.264/AVC

H.264 は広く使用されているビデオ圧縮規格で、AVC (Advanced Video Coding) としても知られています。これは、高品質を維持しながらビデオ ファイルのサイズを大幅に削減できる非可逆圧縮技術です。H.264 は、インターネット ビデオの送信と保存に広く使用されており、HTML5 などのさまざまなプラットフォームに適用できます。同時に、H.264 はスケーラブルなフレームワーク、つまり SVC (スケーラブル ビデオ コーディング) もサポートしています。これは、ネットワーク帯域幅に応じてビデオの定義を自動的に調整し、最高の視聴体験を提供します。

FFmpeg では、libx264エンコーダーを使用して生のビデオ データを H.264 形式のビデオにエンコードできます。次に例を示します。

ffmpeg -i input.mp4 -c:v libx264 -preset veryslow -crf 18 output.mp4

ここでは、出力ファイルを H.264 形式として指定し、-c:v libx264オプションを使用してlibx264エンコーダを選択します。また、-preset veryslow最も遅いエンコード速度を使用してより良いビデオ品質を達成することを意味し、-crf 18ビデオ品質を指定します (値が小さいほど、品質が高くなります)。

6.2 H.265/HEVC

H.265 とも呼ばれる HEVC (High Efficiency Video Coding) は、新しいビデオ圧縮規格です. H.264 と比較して、H.265 は圧縮効率が高く、ビット レートが低く、より高解像度で複雑なビデオを処理できます。コンテンツ。H.265 はエンコードとデコードに強力な計算能力を必要とするため、より高いハードウェア要件が必要になります。

FFmpeg では、libx265エンコーダーを使用して生のビデオ データを HEVC/H.265 形式のビデオにエンコードできます。次に例を示します。

ffmpeg -i input.mp4 -c:v libx265 -preset veryslow -crf 18 output.mp4

これは H.264 の例に似ていますが、-c:v libx265オプションを使用してlibx265エンコーダを選択します。

6.3 VP9

VP9 は、Google が開発した新しいビデオ圧縮規格です。VP9 圧縮技術により、高品質を確保しながら、ビデオ ファイルのサイズを元の半分以下に圧縮できます。VP9 は主に WebM 形式のビデオで使用され、さまざまなプラットフォームに適用できます。

FFmpeg では、libvpx-vp9エンコーダーを使用して生のビデオ データを VP9 形式のビデオにエンコードできます。次に例を示します。

ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 32 -b:v 0 output.webm

ここでは、出力ファイルを VP9 形式で指定し、-c:v libvpx-vp9オプションを使用してlibvpx-vp9エンコーダを選択します。また、-crf 32ビデオ品質を示し(値が大きいほど品質が低くなります)、-b:v 0指定されたビットレートは0であるため、自動的に目標品質に適応します。

6.4 AV1

AV1 は、Alliance for Open Media (AOMedia) コンソーシアムによって開発された新しいビデオ圧縮規格です。H.265 や VP9 と比較して、AV1 は圧縮効率が高く、ビット レートが低く、完全にオープン ソースです。AV1 は徐々に広く使用され始めており、たとえば、YouTube や Netflix などの大規模なビデオ サイトでは、ビデオ エンコーディングに AV1 が使用され始めています。

7. まとめ

結論として、FFmpeg は、さまざまなオーディオおよびビデオ形式の処理に使用できる非常に強力なマルチメディア ソリューションです。ビデオのデコード処理では、ビデオ データを正しくデコードするために、ビデオ デコーダ、フレーム レート制御、デコーダの出力形式、ビデオのエンコード形式、およびその他の関連する知識を理解する必要があります。

おすすめ

転載: blog.csdn.net/irainsa/article/details/130208349