【Qt】之音视频编程2:QtAV的使用篇

QtAV 基本播放控制功能实现(C++ & QML)

QtAV 提供了完整的播放控制 API,支持 播放、暂停、停止、快进快退、截屏 等功能。以下是具体实现方法:


1. C++ 控制方式

基本播放控制

cpp 复制代码
#include <QtAV>
#include <QtAV/AVPlayer.h>

// 初始化播放器
QtAV::AVPlayer player;

// 设置播放文件
player.setFile("video.mp4");  

// 播放
player.play();

// 暂停
player.pause();

// 继续播放(从暂停状态恢复)
player.play();  // 重新播放 或 player.togglePause(); 从播放位置继续播放

// 停止(重置状态)
player.stop();

快进/快退(跳转进度)

cpp 复制代码
// 快进 10 秒
qint64 currentPos = player.position();
player.seek(currentPos + 10000);  // 单位:毫秒

// 快退 5 秒
player.seek(currentPos - 5000); // 重载形式1 直接设置毫秒

// 跳转到 50% 进度
player.seek(0.5); // 重载形式2 直接设置进度

总时长 player.duration()

截屏(保存当前帧)

cpp 复制代码
// 截屏并保存为 PNG
QtAV::VideoOutput *videoOutput = new QtAV::VideoOutput;
player.setRenderer(videoOutput);

// 捕获当前帧
QImage image = videoOutput->frame();
image.save("screenshot.png");

2. QML 控制方式

基本播放控制

qml 复制代码
import QtQuick 2.0
import QtAV 1.7

Item {
    width: 800
    height: 600

    AVPlayer {
        id: avPlayer
        source: "video.mp4"
    }

    VideoOutput {
        source: avPlayer
        anchors.fill: parent
    }

    // 播放/暂停按钮
    Button {
        text: avPlayer.isPlaying ? "暂停" : "播放"
        onClicked: avPlayer.isPlaying ? avPlayer.pause() : avPlayer.play()
    }

    // 停止按钮
    Button {
        text: "停止"
        onClicked: avPlayer.stop()
    }
}

快进/快退

qml 复制代码
// 快进 10 秒
Button {
    text: "快进"
    onClicked: avPlayer.seek(avPlayer.position + 10000)
}

// 快退 5 秒
Button {
    text: "快退"
    onClicked: avPlayer.seek(avPlayer.position - 5000)
}

截屏

qml 复制代码
Button {
    text: "截屏"
    onClicked: {
        const image = videoOutput.captureFrame()
        image.save("screenshot.png")
    }
}

3. 进阶功能

播放速度控制

cpp 复制代码
// 2 倍速播放
player.setSpeed(2.0);

// 0.5 倍慢放
player.setSpeed(0.5);

音量控制

cpp 复制代码
player.audio()->setVolume(0.5);  // 0~1.0

获取播放信息

cpp 复制代码
qint64 totalTime = player.duration();  // 总时长(毫秒) play播放后才能获取到
qint64 currentTime = player.position(); // 当前进度
bool isPlaying = player.isPlaying();

4. 信号与槽(监听状态)

cpp 复制代码
// 监听播放状态变化
connect(&player, &AVPlayer::stateChanged, [](QtAV::AVPlayer::State state) {
    if (state == QtAV::AVPlayer::PlayingState) {
        qDebug() << "开始播放";
    } else if (state == QtAV::AVPlayer::PausedState) {
        qDebug() << "已暂停";
    }
});

// 监听进度变化
connect(&player, &AVPlayer::positionChanged, [](qint64 pos) {
    qDebug() << "当前进度:" << pos;
});

5. 完整示例(C++ 播放器)

cpp 复制代码
#include <QApplication>
#include <QtAV>
#include <QtAV/AVPlayer.h>
#include <QtAV/VideoOutput.h>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QtAV::AVPlayer player;
    QtAV::VideoOutput output;
    output.setRenderer(&player);

    player.setFile("video.mp4");
    player.play();

    // 窗口显示
    output.widget()->show();

    return a.exec();
}

总结

功能 C++ 方法 QML 属性/方法
播放 player.play() avPlayer.play()
暂停 player.pause() avPlayer.pause()
停止 player.stop() avPlayer.stop()
快进/快退 player.seek(pos + 10000) avPlayer.seek(pos + 10000)
截屏 videoOutput->frame().save() videoOutput.captureFrame()
倍速播放 player.setSpeed(2.0) avPlayer.playbackRate = 2.0

将 QtAV 播放窗口集成到自定义界面(C++ & QML)

你可以通过 Qt Widgets(C++)QML 方式将 QtAV 的播放窗口嵌入到自己的 UI 中,并在下方添加控制按钮。以下是两种实现方法:


1. C++ 方式(Qt Widgets)

目标布局

复制代码
+-----------------------+
|      QtAV 播放窗口      |
+-----------------------+
| [播放] [暂停] [停止] ... |
+-----------------------+

代码实现

cpp 复制代码
#include <QApplication>
#include <QtAV>
#include <QtAV/AVPlayer.h>
#include <QtAV/VideoOutput.h>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // 主窗口
    QWidget mainWindow;
    mainWindow.setWindowTitle("自定义播放器");
    mainWindow.resize(800, 600);

    // 垂直布局
    QVBoxLayout *layout = new QVBoxLayout(&mainWindow);

    // 1. 添加 QtAV 播放窗口
    QtAV::AVPlayer *player = new QtAV::AVPlayer;
    QtAV::VideoOutput *videoOutput = new QtAV::VideoOutput;
    player->setRenderer(videoOutput);
    player->setFile("video.mp4");

    // 将 VideoOutput 的 QWidget 添加到布局
    layout->addWidget(videoOutput->widget());

    // 2. 添加控制按钮
    QHBoxLayout *buttonLayout = new QHBoxLayout;

    QPushButton *playButton = new QPushButton("播放");
    QPushButton *pauseButton = new QPushButton("暂停");
    QPushButton *stopButton = new QPushButton("停止");
    QPushButton *screenshotButton = new QPushButton("截屏");

    buttonLayout->addWidget(playButton);
    buttonLayout->addWidget(pauseButton);
    buttonLayout->addWidget(stopButton);
    buttonLayout->addWidget(screenshotButton);

    layout->addLayout(buttonLayout);

    // 按钮信号槽连接
    QObject::connect(playButton, &QPushButton::clicked, [player]() {
        player->play();
    });
    QObject::connect(pauseButton, &QPushButton::clicked, [player]() {
        player->pause();
    });
    QObject::connect(stopButton, &QPushButton::clicked, [player]() {
        player->stop();
    });
    QObject::connect(screenshotButton, &QPushButton::clicked, [videoOutput]() {
        QImage image = videoOutput->frame();
        image.save("screenshot.png");
        qDebug() << "截图已保存!";
    });

    mainWindow.show();
    return app.exec();
}

关键点

  1. VideoOutput::widget()
    将 QtAV 的视频渲染器转换为 QWidget,嵌入到你的布局中。
  2. 使用 QVBoxLayout + QHBoxLayout
    垂直排列播放窗口和按钮栏,水平排列按钮。
  3. 信号槽控制播放器
    通过按钮的 clicked 信号调用 AVPlayer 的对应方法。

2. QML 方式(更简洁的 UI 设计)

目标布局

qml 复制代码
ColumnLayout {
    VideoOutput { /* 播放窗口 */ }
    RowLayout { /* 按钮行 */ }
}

代码实现

qml 复制代码
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtAV 1.7

ApplicationWindow {
    width: 800
    height: 600
    visible: true
    title: "QML 自定义播放器"

    ColumnLayout {
        anchors.fill: parent

        // 1. 播放窗口
        VideoOutput {
            id: videoOutput
            Layout.fillWidth: true
            Layout.fillHeight: true
            source: avPlayer
        }

        // 2. 按钮控制栏
        RowLayout {
            Layout.alignment: Qt.AlignHCenter

            Button {
                text: avPlayer.isPlaying ? "暂停" : "播放"
                onClicked: avPlayer.isPlaying ? avPlayer.pause() : avPlayer.play()
            }
            Button {
                text: "停止"
                onClicked: avPlayer.stop()
            }
            Button {
                text: "快进+10s"
                onClicked: avPlayer.seek(avPlayer.position + 10000)
            }
            Button {
                text: "截屏"
                onClicked: {
                    const image = videoOutput.captureFrame()
                    image.save("screenshot.png")
                    console.log("截图已保存!")
                }
            }
        }
    }

    // 播放器实例
    AVPlayer {
        id: avPlayer
        source: "video.mp4"
    }
}

关键点

  1. VideoOutput 绑定 AVPlayer
    通过 source: avPlayer 关联播放器和渲染窗口。
  2. 动态按钮文本
    avPlayer.isPlaying 控制"播放/暂停"按钮的文本切换。
  3. captureFrame() 截屏
    直接调用 VideoOutput 的接口保存当前帧。

3. 进阶优化

(1) 进度条控制(C++ 示例)

cpp 复制代码
// 添加 QSlider 到布局
QSlider *progressSlider = new QSlider(Qt::Horizontal);
layout->addWidget(progressSlider);

// 更新进度条
QObject::connect(player, &QtAV::AVPlayer::positionChanged, [=](qint64 pos) {
    progressSlider->setValue(pos);
});
QObject::connect(progressSlider, &QSlider::sliderMoved, [=](int value) {
    player->seek(value);
});

(2) 音量控制(QML 示例)

qml 复制代码
Slider {
    from: 0
    to: 100
    value: 50
    onMoved: avPlayer.audio.volume = value
}
相关推荐
RTC实战笔记1 天前
实时互动数字人怎么做,才不是一个只会说话的视频?
音视频·数字人·rtc·数字人接入
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner2 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz7 天前
QML Hello World 入门示例
qt
xcyxiner10 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner11 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner11 天前
DicomViewer (添加模型类)3
qt
xcyxiner12 天前
DicomViewer (目录调整) 2
qt
xcyxiner12 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
RTC实战笔记13 天前
Android 实时音视频接入教程:媒体补充增强信息(SEI)
音视频·媒体·rtc