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();
}
关键点
VideoOutput::widget()
将 QtAV 的视频渲染器转换为QWidget
,嵌入到你的布局中。- 使用
QVBoxLayout
+QHBoxLayout
垂直排列播放窗口和按钮栏,水平排列按钮。 - 信号槽控制播放器
通过按钮的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"
}
}
关键点
VideoOutput
绑定AVPlayer
通过source: avPlayer
关联播放器和渲染窗口。- 动态按钮文本
avPlayer.isPlaying
控制"播放/暂停"按钮的文本切换。 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
}