[C++] FFmpeg: введение и примеры использования аудио- и видеобиблиотеки
[C++] FFmpeg: введение и примеры использования аудио- и видеобиблиотеки

😏1. Знакомство с аудио- и видеобиблиотекой FFmpeg.

ffmpegОфициальный сайт:http://www.ffmpeg.org/

FFmpegЭто звук с открытым исходным кодомвидео Библиотека,Предоставляет такие функции, как обработка аудиофайлов, перекодирование, декодирование, кодирование и воспроизведение. Это полноценное кроссплатформенное решение.,Поддерживает несколько аудиоформатов,И предоставляет различные API и инструменты для обработки аудиоданных.

FFmpegК основным компонентам структуры относятся:AVFormetПакетный модуль、AVCodecкомпилироватьдекодированиемодуль、AVFilterфильтрмодуль、AVDeviceAVUtilждатьмодуль Библиотека。

Вот краткое введение в некоторые базовые знания о библиотеке FFmpeg:

1. Кодер и декодер FFmpeg предоставляет множество кодеров и декодеров для обработки различных аудиоформатов, таких как H.264, MPEG-4, AAC и т. д. Вы можете использовать функции avcodec_find_encoder и avcodec_find_decoder для поиска доступных кодеров и декодеров, а также использовать функцию avcodec_open2 для открытия нужного вам кодера или декодера.

2. Инкапсуляция и декапсуляция формата FFmpeg может обрабатывать различные форматы аудиофайлов, такие как MP4, AVI, WAV и т. д. Он использует формат инкапсуляции для упаковки аудиопотоков в контейнер. Распространенные форматы упаковки включают MP4, AVI, FLV, MKV и т. д. Вы можете использовать функцию avformat_open_input, чтобы открыть аудиофайл, и использовать функцию av_read_frame, чтобы прочитать аудиоданные в файле.

3. Кадры и пакеты В FFmpeg аудиоданные организованы в кадры и пакеты. Аудиоданные обычно организованы в данные PCM, при этом каждый семпл соответствует одному кадру данных, тогда как видеоданные организованы в серию ключевых и неключевых кадров.

4. Соглашение FFmpeg может обрабатывать различные протоколы потокового аудио, такие как RTSP, RTMP, HTTP и т. д. Вы можете использовать функцию avformat_open_input, чтобы открыть сетевой аудиопоток, и использовать функцию av_read_frame, чтобы прочитать пакет данных.

😊2. Конфигурация среды.

Настройте среду следующим образом:

Язык кода:javascript
копировать
# удачная установка
sudo apt install ffmpeg
ffmpeg -version
# Вы также можете выбрать установку из исходного кода.

# Windows можно скачать с официального сайта.

Пример компиляции:

Язык кода:javascript
копировать
g++ -o main main.cpp -lavformat -lavcodec -lavutil

Пример CMakeLists.txt:

Язык кода:javascript
копировать
cmake_minimum_required(VERSION 3.19)
project(ffmpeg_demo)

set(CMAKE_CXX_STANDARD 14)

set(FFMPEG_ROOT "D:/develop/ffmpeg611_mingw/mingw64")
include_directories(${FFMPEG_ROOT}/include)
link_directories(${FFMPEG_ROOT}/lib)
set(FFMPEG_LIBS avcodec avformat avutil avdevice avfilter postproc swresample swscale)
#link_directories(${FFMPEG_ROOT}/bin)
#set(FFMPEG_LIBS avcodec-60 avformat-60 avutil-58 swscale-7)

add_executable(ffmpeg_demo main.cpp)
target_link_libraries(ffmpeg_demo ${FFMPEG_LIBS})

😆3. Примеры приложений.

видео

Съемочная камера:

Язык кода:javascript
копировать
ffmpeg -f video4linux2 -s  640x480 -pixel_format yuyv422  -i /dev/video0  out.mp4 -loglevel debug
ffmpeg -f x11grab -framerate 25 -video_size 1280*720 -i :0.0 out.mp4	# Собери рабочий стол х11

преобразование формата видео:

Язык кода:javascript
копировать
ffmpeg -i input.avi output.mp4

Преобразование частоты кадров:

Язык кода:javascript
копировать
ffmpeg -i input.avi -r 24 output.mp4

Командная строка многоканального сращивания:

Язык кода:javascript
копировать
# Двустороннее горизонтальное сращивание
ffmpeg -i out1.mp4 -i out2.mp4 -filter_complex "[0:v]pad=iw*2:ih*1[a];[a][1:v]overlay=w" out.mp4
# Двустороннее вертикальное сращивание
ffmpeg -i out1.mp4 -i out2.mp4 -filter_complex "[0:v]pad=iw:ih*2[a];[a][1:v]overlay=0:h" out.mp4
# Трехстороннее горизонтальное сращивание видео
ffmpeg -i out1.mp4 -i out2.mp4 -i out3.mp4 -filter_complex "[0:v]pad=iw*3:ih*1[a];[a][1:v]overlay=w[b];[b][2:v]overlay=2.0*w" out.mp4 
# Трехходовое вертикальное сращивание
ffmpeg -i out1.mp4 -i out2.mp4 -i out3.mp4 -filter_complex "[0:v]pad=iw:ih*3[a];[a][1:v]overlay=0:h[b];[b][2:v]overlay=0:2.0*h" out.mp4
# Четырехстороннее расположение видео2X2
ffmpeg -i out1.mp4 -i out2.mp4 -i out3.mp4 -i out4.mp4 -filter_complex "[0:v]pad=iw*2:ih*2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" out.mp4

видеоPush-стриминг:

Язык кода:javascript
копировать
ffmpeg -r 100 -i /dev/video0 -f flv udp://192.168.111.121:9666
ffplay -max_delay 10 udp://192.168.111.121:9666
# Оригинальное потоковое аудио
ffmpeg  -f alsa -ar 11025 -ac 2 -i hw:0 -i /dev/video0 -f flv udp://192.168.111.121:9666
Аудио

Преобразование аудиоформата:

Язык кода:javascript
копировать
ffmpeg64 -i null.ape -ar 44100 -ac 2 -ab 16k -vol 50 -f mp3 null.mp3
Примечание. -i представляет входные параметры.
          -acodec aac (кодирование аудио с помощью AAC) 
          -ar Установить частоту дискретизации аудио
          -ac  Установите количество аудиоканалов
          -ab Установить битрейт звука
          -vol <процент> Установить громкость

# Или создайте список, содержащий необходимое аудио
ffmpeg -safe 0 -f concat -i list.txt -c copy out.wav

Монтаж аудио:

Язык кода:javascript
копировать
# Создайте новый список, содержащий необходимое аудио.
touch list.txt
file '1.mp3'
file '2.mp3'
ffmpeg -f concat -i list.txt -c copy out.mp3

Запись Аудио:

Язык кода:javascript
копировать
ffmpeg -y -f alsa -i hw:0 -t 00:00:03 -ar 8000 -ac 1 out.mp3

АудиоPush-стриминг:

Язык кода:javascript
копировать
ffmpeg  -f alsa -i hw:0 -ar 11025 -ac 1 -f flv udp://192.168.111.121:9666

Другие ссылки:

Язык кода:javascript
копировать
Реализация видеоплеера: http://t.csdn.cn/N6Vuo

Реализация аудиоплеера: http://t.csdn.cn/zJuXn

Прочитайте камеру через opencv: http://t.csdn.cn/mGCog

Нажмите камеру rtsp Трансляция: http://t.csdn.cn/YrLMm
пример С++
Язык кода:javascript
копировать
extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}
#include <map>

int main(int argc, char *argv[])
{
    if (argc < 3) {
        printf("remux <input> <output>\n");
        return -1;
    }

    const char *in_filename  = argv[1];
    const char *out_filename = argv[2];

    // input
    AVFormatContext *decoder_fmt_ctx = nullptr;
    if (avformat_open_input(&decoder_fmt_ctx, in_filename, nullptr, nullptr) < 0) {
        fprintf(stderr, "failed to open the %s file.\n", in_filename);
        return -1;
    }

    if (avformat_find_stream_info(decoder_fmt_ctx, nullptr) < 0) {
        fprintf(stderr, "not find stream info.\n");
        return -1;
    }

    av_dump_format(decoder_fmt_ctx, 0, in_filename, 0);

    // output
    AVFormatContext *encoder_fmt_ctx = nullptr;
    if (avformat_alloc_output_context2(&encoder_fmt_ctx, nullptr, nullptr, out_filename) < 0) {
        fprintf(stderr, "failed to alloc output-context memory.\n");
        return -1;
    }

    // map streams
    //
    // a media file always contains several streams, like video and audio streams.
    std::map<unsigned int, int> stream_mapping{};
    int stream_idx = 0;
    for (unsigned int i = 0; i < decoder_fmt_ctx->nb_streams; i++) {
        AVCodecParameters *decode_params = decoder_fmt_ctx->streams[i]->codecpar;
        if (decode_params->codec_type != AVMEDIA_TYPE_VIDEO &&
            decode_params->codec_type != AVMEDIA_TYPE_AUDIO &&
            decode_params->codec_type != AVMEDIA_TYPE_SUBTITLE) {
            stream_mapping[i] = -1;
            continue;
        }

        stream_mapping[i] = stream_idx++;

        AVStream *encode_stream = avformat_new_stream(encoder_fmt_ctx, nullptr);
        if (encode_stream == nullptr) {
            fprintf(stderr, "failed to create a stream for output.\n");
            return -1;
        }

        if (avcodec_parameters_copy(encode_stream->codecpar, decode_params) < 0) {
            fprintf(stderr, "failed to copy parameters.\n");
            return -1;
        }
    }

    // open the output file
    if (!(encoder_fmt_ctx->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&encoder_fmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) {
            printf("can not open the output file : %s.\n", out_filename);
            return -1;
        }
    }

    // header
    if (avformat_write_header(encoder_fmt_ctx, nullptr) < 0) {
        fprintf(stderr, "can not write header to the output file.\n");
        return -1;
    }

    av_dump_format(encoder_fmt_ctx, 0, out_filename, 1);

    // copy streams
    AVPacket *packet     = av_packet_alloc();
    int64_t frame_number = 0;
    while (av_read_frame(decoder_fmt_ctx, packet) >= 0) {
        if (stream_mapping[packet->stream_index] < 0) {
            // the packet is reference-counted.
            // the ffmpeg is a C library, we need unreference the buffer manually
            av_packet_unref(packet);
            continue;
        }

        // convert the timestamps from the time base of input stream to the time base of output stream
        //
        // In simple terms, a time base is a rescaling of the unit second, like 1/100s, 1001/24000s, and
        // each stream has its own time base. The timestamps of the packets are based on the time base of
        // their streams, timestamps of the same value have different meanings depending on the time unit.
        //
        // It is not necessary in this example since the time base of input and output streams is the same.
        av_packet_rescale_ts(packet, decoder_fmt_ctx->streams[packet->stream_index]->time_base,
                             encoder_fmt_ctx->streams[stream_mapping[packet->stream_index]]->time_base);

        printf(
                " -- %s] packet = %6ld, pts: %6ld, dts: %6ld, duration: %5ld\n",
                av_get_media_type_string(encoder_fmt_ctx->streams[packet->stream_index]->codecpar->codec_type),
                frame_number++, packet->pts, packet->dts, packet->duration);

        packet->stream_index = stream_mapping[packet->stream_index];
        // write the packet to the output file
        // this function will take the owership of the packet, and packet will be blank
        if (av_interleaved_write_frame(encoder_fmt_ctx, packet) != 0) {
            fprintf(stderr, "failed to write frame.\n");
            return -1;
        }
    }

    // write the trailer to the output file and close it
    av_write_trailer(encoder_fmt_ctx);
    if (encoder_fmt_ctx && !(encoder_fmt_ctx->oformat->flags & AVFMT_NOFILE))
        avio_closep(&encoder_fmt_ctx->pb);

    // release the resources
    // let's not think about the abnormal exit for simplicity
    av_packet_free(&packet);
    avformat_close_input(&decoder_fmt_ctx);
    avformat_free_context(encoder_fmt_ctx);

    return 0;
}

😆4. Пример видеоплеера.

видеопроект игрокаGithubадрес:https://github.com/pockethook/player.git

видеопроект игрока В основном используютиспользоватьFFmpegДелатьвидеокомпилироватьдекодирование,использоватьSDLсделать рендеринг。

Скомпилируйте и запустите:

Язык кода:javascript
копировать
make
./player xxx.mp4
boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose