Мультимедиа

Кодирование и транскодирование: QMediaRecorder, форматы и кодеки

Введение

Статья 471 кратко использовала QMediaRecorder для записи видео — в этой статье разберём его подробнее, включая настройку конкретных кодеков и контейнерных форматов, а также общий принцип транскодирования (преобразования из одного формата/кодека в другой).

Концепция

QMediaRecorder отвечает за кодирование захватываемого аудио/видеопотока (от QMediaCaptureSession, статья 471) в конкретный, сжатый формат и сохранение результата в файл — настраивается через QMediaFormat, определяющий контейнер (контейнерный формат файла, например MP4 или WebM, определяющий, как разные потоки данных упаковываются вместе) и отдельно кодеки для видео- и аудиопотока (например, H.264 для видео, AAC для звука) внутри этого контейнера. Транскодирование — процесс преобразования уже существующего медиафайла из одного формата/кодека в другой (например, для совместимости с конкретным устройством или для уменьшения размера файла) — для Qt Multimedia это требует совмещения декодирования через QMediaPlayer с последующим повторным кодированием, либо использования внешнего инструмента (статья 477, FFmpeg) для более полного контроля над процессом.

Пример кода

// Настройка конкретного формата записи через QMediaFormat
#include <QMediaRecorder>
#include <QMediaFormat>

void configureRecorder(QMediaRecorder *recorder)
{
    QMediaFormat format;
    format.setFileFormat(QMediaFormat::MPEG4);     // контейнер MP4
    format.setVideoCodec(QMediaFormat::VideoCodec::H264);
    format.setAudioCodec(QMediaFormat::AudioCodec::AAC);

    recorder->setMediaFormat(format);
    recorder->setQuality(QMediaRecorder::HighQuality);
    recorder->setVideoResolution(1920, 1080);
    recorder->setVideoFrameRate(30);
}
// Проверка реально поддерживаемых комбинаций контейнера/кодеков на конкретной системе
void printSupportedFormats(QMediaRecorder *recorder)
{
    const QList<QMediaFormat::FileFormat> containers = recorder->mediaFormat().supportedFileFormats(QMediaFormat::Encode);

    for (auto container : containers) {
        QMediaFormat testFormat;
        testFormat.setFileFormat(container);
        qDebug() << "Контейнер:" << QMediaFormat::fileFormatName(container);

        for (auto codec : testFormat.supportedVideoCodecs(QMediaFormat::Encode)) {
            qDebug() << "  Видеокодек:" << QMediaFormat::videoCodecName(codec);
        }
    }
}

Пояснения к коду

configureRecorder показывает явную настройку всех ключевых параметров записи — комбинация MP4-контейнера с H.264-видео и AAC-звуком выбрана как одна из наиболее широко поддерживаемых и совместимых комбинаций для большинства современных устройств воспроизведения, хотя конкретный выбор должен учитывать реальные требования совместимости приложения. printSupportedFormats показывает важный практический паттерн — перебор реально поддерживаемых на текущей, конкретной системе комбинаций контейнера и кодеков, что особенно важно, поскольку (аналогично подводному камню статьи 467 про аудиоформаты) реальная поддержка зависит от установленного мультимедийного бэкенда конкретной системы, и попытка использовать неподдерживаемую комбинацию без предварительной проверки может привести к неожиданной ошибке записи.

Подводные камни

  • Жёсткая, не проверяемая программно настройка конкретного кодека без учёта возможного отсутствия его поддержки на целевой системе — приложение, протестированное на разработческой машине с полным набором установленных кодеков, может столкнуться с ошибкой записи на системе пользователя без поддержки выбранного, изначально захардкоженного кодека; для надёжного поведения стоит либо проверять поддержку через supportedVideoCodecs()/supportedAudioCodecs() перед записью, либо предусмотреть осмысленную обратную связь пользователю при неудачной попытке.
  • Выбор избыточно высокого качества/битрейта записи без учёта реальных требований приложения и доступного места на дискеQMediaRecorder::HighQuality для длительной записи видео в высоком разрешении может генерировать файлы значительного размера за единицу времени, и для приложений с длительной записью (например, видеонаблюдение) выбор качества должен явно балансировать визуальное качество с практическими ограничениями по объёму сохраняемых данных.
  • Попытка транскодирования через простое декодирование QMediaPlayer и повторное кодирование QMediaRecorder без понимания, что Qt Multimedia API не предназначен изначально именно для пакетного, программного транскодирования файлов — этот API ориентирован на запись в реальном времени от живого источника захвата (камеры/микрофона), и для надёжного, эффективного транскодирования уже существующих файлов специализированные инструменты (FFmpeg, статья 477) обычно дают значительно больший контроль и эффективность по сравнению с обходным путём через декодирование-перезахват-перекодирование средствами Qt Multimedia.
  • Игнорирование того, что некоторые комбинации кодеков лицензионно ограничены (особенно H.264 в некоторых юрисдикциях/конфигурациях для коммерческого использования без соответствующей лицензии) — перед выбором конкретного кодека для коммерческого, распространяемого приложения стоит проверить лицензионные условия использования этого кодека в конкретном юридическом и коммерческом контексте, особенно для кодеков, не являющихся полностью свободными от патентных ограничений (в отличие, например, от открытых, свободных от патентных проблем альтернатив, как VP9/AV1 для видео).