使用Qt进行音视频播放


  Qt对音视频的播放和控制,相机拍照,收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用,而原来Qt4中用于实现多媒体功能的Phonon模块已经被移除。

  新的Qt Multimedia模块提供了丰富的接口,使读者可以轻松地使用平台的多媒体功能,例如,进行多媒体播放,使用相机和收音机等。该模块还分别提供了一组QML类型和一组C++类来处理多媒体内容。

C++ 中多媒体模块可以实现的功能,对应的示例程序以及需要使用的C++类如:
在这里插入图片描述

  Qt的多媒体接口建立在底层平台的多媒体框架之上,这就意味着对于各种编解码器的支持依赖于使用的平台。如果要访问一些平台相关的设置,或者将Qt多媒体接口移植到新的平台,则可以参考Qt帮助中的Multimedia Backend Development文档。

  另外,如果要使用多媒体模块中的内容,则需要在.pro项目文件中添加如下代码,引入多媒体模块:

QT += multimedia

播放音频

  在Qt中,要使计算机发出响声,最简单的方法是调用QApplication::beep()静态函数。而Qt Multimedia模块中提供了多个类来实现不同层次的音频输入,输出和处理。

播放压缩音频

  Qt中播放一个音频(比如MP3音频)十分简单,通常使用QMediaPlayer,只需要几行代码即可完成。QMediaPlayer被设计用来媒体播放,可以播放音频,视频和网络广播。

下面看看如何使用该类播放音频文件:

player = new QMediaPlayer;
player->setMedia(QUrl::fromLocalFile("../playMedia/song.mp3"));
player->play();

  上面setMedia()设置的媒体资源是本地的,如果要播放网络歌曲,则只需要将地址修改为QUrl网络地址即可。QMedicaPlayer支持的音频文件格式取决于操作系统以及用户安装的媒体插件。

低延迟声音效果

  QSoundEffect类可以使用一种低延迟方式来播放为未压缩的音频文件,如.wav文件,它非常适合用来播放与用户交互时的音效,如弹出框提示音,虚拟键盘按键音,游戏音效等。

  当然,如果并不需要低延迟效果,那么最好使用QMediaPlayer来播放音频,因为其中支持更多的媒体格式且占用资源更少。

  下面通过一个例子来看一下QSoundEffect的应用。

  新建一个Qt Widgets应用,项目名称mysoundeffect,类名MainWindow和基类QMainWindow保持默认即可。

完成后在项目文件mysoundeffct.pro中修改代码如下:

QT += core gui multimedia

然后在mainwindow.h中添加前置声明:

// 前置声明
class QSoundEffect;

添加好后,在向其中声明一个私有变量:

private:
    QSoundEffect *effect;

再到mainwindow.cpp文件,向构造函数中添加如下代码:

effect = new QSoundEffect(this);
effect->setSource(QUrl::fromLocalFile("../mysoundeffect/sound.wav"));
effect->setVolume(0.25f);	// 设置音量大小(取值范围是0.0 ~ 1.0)

  双击mainwindow.ui进入设计模式,向界面中拖入两个PushButton和一个SpinBox,并将两个按钮的文本分别改为"播放"和"停止"。然后更改SpinBox的属性,将当前值value设置为1。最后转到两个按钮的clicked()槽和SpinBox的valueChanged(int)槽。

对这三个槽函数的定义更改如下:

// 播放按钮
void MainWindow::on_playButton_clicked()
{
    effect->play();
}

// 停止按钮
void MainWindow::on_stopButton_clicked()
{
    effect->stop();
}

void MainWindow::on_spinBox_valueChanged(int arg1)
{
    effect->setLoopCount(arg1); // 设置音乐的播放次数(设为0或1时都表示只播放一次,设为QSoundEffect::Infinite表示无限重复)
}

在这里插入图片描述

播放视频

  前面提到过QMediaPlayer不仅可以播放音频,还可以用来播放视频。不过如果要视频在界面上显示出来,还需要其他类来进行辅助,比如QVideoWidget,QGraphicsVideoItem或者自定义的类。而像GIF格式的动画类型,则可以使用QMovie播放。

播放视频文件

  视频文件可以通过QMediaPlayer进行播放,但是要在界面上显示视频内容,需要借助QVideoWidget或者QGraphicsVideoItem类,这两个类都属于Qt MultimediaWidgets模块。

  QVideoWidget继承自QWidget,所以它可以作为一个普通窗口部件进行显示,也可以嵌入到其他窗口中。将QVideoWidget指定为QMediaPlayer的视频输出窗口后,就可以显示播放的视频画面。当然,如果不为播放器设置视频输出界面,播放器也是可以播放视频的,不过只会出现声音而没有画面。

  使用QVideoWidget可以设置视频的亮度,对比度,色相和饱和度,还可以设置全屏显示,并且为这些功能设置了相应的信号和槽。

  新建Qt Widgets应用,项目名称为myvideowidget,基类选择QWidget,类名保持Widget不变。项目创建完成后,将myvideowidget.pro修改如下:

QT += core gui multimedia multimediawidgets

完成后保存该文件,然后到widget.h中添加类的前置声明:

class QMediaPlayer;
class QVideoWidget;

  双击widget.ui进入设计模式,将Widget界面的宽度属性设置为600,高度设置为400,然后往界面上拖入4个标签Label和4个水平滑块Horizontal Slider,一个标签对应一个滑块,分为4组。

  将4个标签显示文本分别设置为"亮度",“对比度”,“色相"和"饱和度”,而对应的滑块的objectName分别设置为brightnessSlider,contrastSlider,hueSlider和saturationSlider。最后将4个滑块的minimum属性设置为-100,maximum属性设置为100。

下面进入widget.cpp文件,先添加头文件包含:

#include "widget.h"
#include "ui_widget.h"
#include <QMediaPlayer>
#include <QVideoWidget>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    player = new QMediaPlayer(this);	
    videoWidget = new QVideoWidget(this);	// 新建视频播放器
    videoWidget->resize(600, 300);
    player->setVideoOutput(videoWidget);	// 指定视频输出窗口(一个播放器)
    player->setMedia(QUrl::fromLocalFile("../myvideowidget/video.WMV"));
    player->play();

    // 亮度
    ui->brightnessSlider->setValue(videoWidget->brightness());
    connect(ui->brightnessSlider, &QSlider::sliderMoved, videoWidget, &QVideoWidget::setBrightness);
    connect(videoWidget, &QVideoWidget::brightnessChanged, ui->brightnessSlider, &QSlider::setValue);

    // 对比度
    ui->contrastSlider->setValue(videoWidget->contrast());
    connect(ui->contrastSlider, &QSlider::sliderMoved, videoWidget, &QVideoWidget::setContrast);
    connect(videoWidget, &QVideoWidget::contrastChanged, ui->contrastSlider, &QSlider::setValue);

    // 色相
    ui->hueSlider->setValue(videoWidget->hue());
    connect(ui->hueSlider, &QSlider::sliderMoved, videoWidget, &QVideoWidget::setHue);
    connect(videoWidget, &QVideoWidget::hueChanged, ui->hueSlider, &QSlider::setValue);

    // 饱和度
    ui->saturationSlider->setValue(videoWidget->saturation());
    connect(ui->saturationSlider, &QSlider::sliderMoved, videoWidget, &QVideoWidget::setSaturation);
    connect(videoWidget, &QVideoWidget::saturationChanged, ui->saturationSlider, &QSlider::setValue);
}

Widget::~Widget()
{
    delete ui;
}

在这里插入图片描述

  再来看看QGraphicsVideoItem,它继承自QGraphicsObject,且提供了一个窗口作为图形项嵌入到场景中以显示视频内容。

  新建一个空项目,模板选择其中项目中的Empty qmake Project,项目名称myvideoitem,在myvideoitem.pro中添加如下代码:

QT += multimedia multimediawidgets

  然后再向项目中添加新的C++ Source File,名称为main.cpp,完成后更改其内容如下:

#include <QApplication>
#include <QMediaPlayer>
#include <QGraphicsVideoItem>
#include <QGraphicsView>
#include <QGraphicsScene>

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

    QGraphicsScene scene;
    QGraphicsView view(&scene);
    view.resize(600, 320);
    QGraphicsVideoItem item;
    scene.addItem(&item);
    item.setSize(QSizeF(500, 300));
    QMediaPlayer player;
    player.setVideoOutput(&item);
    player.setMedia(QUrl::fromLocalFile("../myvideoitem/video.wmv"));
    player.play();
    view.show();

    return a.exec();
}

  这里首先创建了场景,视图和视频图形项,然后创建了播放器,并将视频图形项作为播放器的视频输出窗口,最后设置了要播放的视频,并显示视图播放视频。这样一来,就在场景中嵌入了视频播放图形项。

使用QMovie播放GIF文件

  实际上,QMovie类并不属于多媒体模块,而是包含在Qt GUI模块。QMovie使用QImageReader来播放没有声音的动画,比如GIF格式的文件,其支持的格式可以使用QMovie::supportedFormats()静态函数获取。

  要播放一个动画,只需要先创建一个QMovie对象,并为其指定要播放的动画文件,然后将QMovie对象传递给QLabel::setMovie()函数,最后调用start()函数来播放动画。

例如使用QMovie类来播放GIF动画:

QLabel label;
QMovie * movie = new QMovie("animations/fire.gif");
label.setMovie(movie);
movie->start();

  还可以使用setPause(true)函数来暂停动画的播放,然后使用setPause(false)来恢复播放;使用stop()函数可以停在动画的播放。QMovie一共有3个状态,这3个状态见下表:
在这里插入图片描述

  每当状态改变时都会发射stateChanged()信号,可以通过关联这个信号来改变播放,暂停等按钮的状态。

  可以使用frameCount()函数来获取当前动画总的帧数;currentFrameNumber()函数可以返回当前帧的序列号,动画第一个帧的序列号为0;如果动画播放到了一个新的帧,QMovie会发射updated()信号,这时可以使用currentImage()或者currentPixmap()函数来获取当前帧的一个副本。

  还可以使用setCacheMode()来设置QMovie的缓存模式,这里有两个选项:

  • QMovie::CacheNone
  • QMovie:CacheAll

  前者是默认选项,不缓冲任何帧;后者是缓存所有的帧。如果指定了QMovie::CacheAll选项,那么就可以使用jumpToframe()来跳转到指定的帧了。另外,还可以使用setSpeed()来设置动画的播放速度,该速度是以原始速度的百分比来衡量的,默认的速度为100%。

下面用一个例子来看一个这些功能的应用。

  新建Qt Widgets应用,项目名称mymovie,类名MainWindow和基类QMainWindow保持不变。项目创建完成后打开设计模式,将界面设计成下面这样:
在这里插入图片描述

  这其中,要设置水平滑动部件Horizontal Slider的tickPosition属性为TickBelow,然后设置间隔tickInterval的数值为10;选中"暂停"按钮的checkable属性;设置SpinBox的后缀suffix属性为"%",最大值maximum为999,当前值value为100。

然后到mainwindow.h文件中添加前置声明:

class QMovie;

再添加私有对象:

QMovie * movie;

更改完成后widget.h中的内容应该如下:

在这里插入图片描述

然后将widget.cpp中的内容改为:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMovie>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label->setAlignment(Qt::AlignCenter);       // Label内的对齐策略
    ui->label->setBackgroundRole(QPalette::Dark);   // 设置label未播放动画时的背景色
    ui->label->setAutoFillBackground(true);

    movie = new QMovie(this);
    movie->setFileName("../mymovie/rain.gif");
    movie->setCacheMode(QMovie::CacheAll);          // 缓存动画的每一帧
    movie->setScaledSize(ui->label->size());        // 动画播放区域的大小和label部件一样
    ui->label->setMovie(movie);
    ui->horizontalSlider->setMinimum(0);
    ui->horizontalSlider->setMaximum(movie->frameCount());
    // 随着动画帧的播放进度条向前移动(每次移动tickInterval个单位,这里是10)
    connect(movie, &QMovie::frameChanged, ui->horizontalSlider, &QSlider::setValue);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
    movie->jumpToFrame(value);      // 调转到前面播放动画时缓存的某一帧
}

void MainWindow::on_startButton_clicked()
{
    movie->start();
}

void MainWindow::on_pauseButton_clicked(bool checked)
{
    movie->setPaused(checked);  // 如果按钮被选中,则暂停动画
}

void MainWindow::on_stopButton_clicked()
{
    movie->stop();
}

void MainWindow::on_screenshotButton_clicked()
{
    int id = movie->currentFrameNumber();
    QPixmap pix = movie->currentPixmap();           // 一帧中保存的图像
    pix.save(QString("../mymovie/%1.png").arg(id)); // 保存gif的当前帧
}

void MainWindow::on_spinBox_valueChanged(int arg1)
{
    movie->setSpeed(arg1);
}

在这里插入图片描述

QMediaPlayer

  前面播放音频,视频时都使用了QMediaPlayer这个类。

  要使用QMediaPlayer进行播放,首先需要使用setMedia(const QMediaContent &media, QIODevice stream = 0)槽函数来指定媒体源。其中,QMediaContent提供了对媒体源的访问,它包含了媒体源的URL和格式信息,一般对于本地媒体只需要指定文件路径即可,如前面代码中那样使用QUrl::fromLocalFile指定路径即可。

  如果这里提供了一个媒体流stream,那么将会直接从流中读取媒体数据而不再对单独的媒体文件进行解析。

  设置完媒体源后,可以使用play()函数进行播放,使用pause(),stop()进行暂停和停止。可以通过currentMedia()来获取当前进行播放的媒体内容,返回类型是QMediaContent。使用duration()获取当前媒体的时长。position()可以获取当前的播放位置,单位为毫秒。使用setPosition()可以跳转到一个播放点,通过关联positionChanged()信号可以随时获取播放进度。使用volume()可以获取当前的播放音量,其范围为0 ~ 100,setVolume()可以用来设置音量大小;而当音量改变时会发射volumeChanged()信号,如果要设置为静音,可以使用setMuted()函数。

下面通过一个例子来讲解以上属性。

  新建Qt Widgets应用,下项目名称mypayer,类名Mainwindow和基类QMainWindow都保持默认即可。完成后在项目文件myplayer.pro中修改代码如下:

QT += core gui multimedia

完成后保存该文件。然后将mainwindow.h文件改为:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMediaPlayer>

namespace Ui {
class MainWindow;
}

class QMediaPlaylist;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QMediaPlayer *player;

private slots:
    void updatePosition(qint64 position);

    void on_playerButton_clicked();
    void on_pauseButton_clicked();
    void on_stopButton_clicked();
    void on_horizontalSlider_sliderMoved(int position);
};

#endif // MAINWINDOW_H

然后在mainwindow.cpp文件中,在构造函数中添加如下代码:

player = new QMediaPlayer(this);
player->setMedia(QUrl::fromLocalFile("..myplayer/music/郝云 - 活着.mp3"));
connect(player, &QMediaPlayer::positionChanged, this, &MainWindow::updatePosition);

  双击mainwindow.ui进入设计模式,然后向界面中拖入一个Horizontal Slider,3个按钮和3个Label,3个按钮显示文本分别设置为"播放",“暂停"和"停止”,同时将3个按钮的objectName分别设为"playButton",“pauseButton"和"stopButton”,3个Label用于后面输出不同的信息。然后再分别转到3个按钮的单击信号槽中,对它们的槽函数做如下定义:

void MainWindow::on_playerButton_clicked()
{
    player->play();
}

void MainWindow::on_pauseButton_clicked()
{
    player->pause();
}

void MainWindow::on_stopButton_clicked()
{
    player->stop();
}

然后再转到horizontalSider的sliderMoved(int)槽,在mainwindow.cpp做出它的定义:

void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
    player->setPosition(position * 1000);
}

最后添加updatePosition()槽的定义:

void MainWindow::updatePosition(qint64 position){
    ui->horizontalSlider->setMaximum(player->duration() / 1000);
    ui->horizontalSlider->setValue(position / 1000);
}

在这里插入图片描述

1. 播放状态

  当QMediaPlayer使用setMedia()设置了媒体源后,setMedia()函数会直接返回,并不等待媒体加载完成,也不会检查可能存在的错误。当媒体的状况发生改变时播放器会发射mediaStatusChanged()信号,可以通过关联该信号来获取媒体加载的一些信息。播放器播放的当前媒体会有9种不同的状况,这9种状况由QMediaPlayer::MediaStatus枚举类型定义,其可取值见下表:
在这里插入图片描述

  另外,当播放器发生错误时会发射error()信号,通过关联该信号可以对相应的错误进行处理。播放器会出现6种不同的错误情况,这6种情况由QMediaPlayer::Error枚举类型定义。其可选值如下:
在这里插入图片描述

  QMediaPlayer进行播放时拥有3种状态,它总是处于这3种状态中的其中一种。这3种状态由QMediaPlayer::State枚举类型定义,其取值见下表:
在这里插入图片描述

  还是在myplayer项目中,继续向其中添加代码。首先在mainwindow.h中声明3个私有槽:

private slots:
	void stateChanged(QMediaPlayer::State state);
	void mediaStatusChanged(QMediaPlayer::MediaStatus status);
	void showError(QMediaPlayer::Error error);

然后到mainwindow.cpp中,现在构造函数中添加信号和槽关联:

connect(player, &QMediaPlayer::stateChanged, this, &MainWindow::stateChanged);
connect(player, &QMediaPlayer::mediaStatusChanged, this, &MainWindow::mediaStatusChanged);
connect(player, static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error)>(&QMediaPlayer::error), this, &MainWindow::showError);

  然后进入设计模式,将上面用于显示媒体状态的3个Label的文本分别改为"mediaStatusLabel",“stateLabel"和"errorLabel”,同时也设置它们的objectName分别为"mediaStatusLabel",“stateLabel"和"errorLabel”。

再转到mainwindow.cpp中对这几个槽做出定义:

void MainWindow::mediaStatusChanged(QMediaPlayer::MediaStatus status){
    switch(status){
        case QMediaPlayer::UnknownMediaStatus:
             ui->mediaStatusLabel->setText(tr("媒体未知状况!"));
             break;
        case QMediaPlayer::NoMedia:
             ui->mediaStatusLabel->setText(tr("没有媒体文件!"));
             break;
        case QMediaPlayer::BufferingMedia:
             ui->mediaStatusLabel->setText(tr("正在缓冲媒体文件!"));
             break;
        case QMediaPlayer::BufferedMedia:
             ui->mediaStatusLabel->setText(tr("媒体文件缓冲完成!"));
             break;
        case QMediaPlayer::LoadingMedia:
             ui->mediaStatusLabel->setText(tr("正在加载媒体!"));
             break;
        case QMediaPlayer::StalledMedia:
             ui->mediaStatusLabel->setText(tr("播放停滞!"));
             break;
        case QMediaPlayer::EndOfMedia:
             ui->mediaStatusLabel->setText(tr("播放结束!"));
             break;
        case QMediaPlayer::LoadedMedia:
             ui->mediaStatusLabel->setText(tr("媒体加载完成!"));
             break;
        case QMediaPlayer::InvalidMedia:
             ui->mediaStatusLabel->setText(tr("不可用的媒体文件!"));
             break;
        default: break;
    }
}

void MainWindow::stateChanged(QMediaPlayer::State state){
    switch(state){
        case QMediaPlayer::StoppedState:
             ui->stateLabel->setText(tr("停止状态!"));
             break;
        case QMediaPlayer::PlayingState:
             ui->stateLabel->setText(tr("播放状态!"));
             break;
        case QMediaPlayer::PausedState:
             ui->stateLabel->setText(tr("暂停状态!"));
             break;
        default: break;
    }
}

void MainWindow::showError(QMediaPlayer::Error error){
    switch(error){
        case QMediaPlayer::NoError:
             ui->errorLabel->setText(tr("没有错误!"));
             break;
        case QMediaPlayer::ResourceError:
             ui->errorLabel->setText(tr("媒体资源无法被解析!"));
             break;
        case QMediaPlayer::FormatError:
             ui->errorLabel->setText(tr("不支持该媒体格式!"));
             break;
        case QMediaPlayer::NetworkError:
             ui->errorLabel->setText(tr("发生了一个网络错误!"));
             break;
        case QMediaPlayer::AccessDeniedError:
             ui->errorLabel->setText(tr("没有播放权限!"));
             break;
        case QMediaPlayer::ServiceMissingError:
             ui->errorLabel->setText(tr("没有发现有效的播放服务!"));
             break;
    }
}

在这里插入图片描述

2. 获取媒体元数据

  可以使用QMediaPlayer的metaData()函数来获取媒体的元数据。QMediaMetaData()命令空间中提供了众多元数据属性。例如,媒体文件的标题Title作者Author和播放时间Duration等。

  每当QMediaPlayer对媒体源进行解析,元数据可用时都会发射metaDataAvailableChanged()信号,可以关联信号来获取当前媒体的相关信息。

下面简单介绍下如何获取常用的几个元数据。

往前面程序中继续添加代码,首先在mainwindow.h文件中添加私有槽声明:

private slots:
	void metaDataAvailableChanged(bool available);

然后到mainwindow.cpp中,在构造函数最后添加信号槽关联:

connect(player, &QMediaPlayer::metaDataAvailableChanged, this, &MainWindow::metaDataAvailableChanged);

然后添加metaDataAvailableChanged()槽的定义:

void MainWindow::metaDataAvailableChanged(bool available)
{
	if(available) {
		QString title = player->metaData("Title").toString();	// 获取媒体标题信息
		QString author = player->metaData("Author").toString();
		setWindowTitle(title + "-" + author);
	}
}

  另外,要注意的是,如果要获取媒体元数据,那么使用setMedia()设置媒体源时一定要使用绝对路径,使用相对路径将无法元数据。所以还要将先前构造函数中的player->setMedia()中的文件路径改为绝对路径。

在这里插入图片描述

3. 播放列表

  QMediaPlaylist类提供了一个播放列表,它其实是一个QMediaContent对象列表,并包含了一些实用功能,QMediaPlayer可以通过setPlaylist()来设置一个播放列表。

  QMediaPlaylist可以通过addMedia()来添加一个QMediaContent对象或者添加一个QMediaContent对象列表作为媒体源,也可以通过insertMedia()将媒体插入到列表任意位置,或者使用load()函数来加载网络资源。使用mediaCount()可以获取列表中媒体的数量,currentMedia()可以获取当前的媒体。使用removeMedia()可以设置删除一个媒体。而clear()可以清空整个播放列表。可以通过next(),previous(),setCurrentIndex()和shuffle()等槽来指定播放列表中的条目进行播放,每当播放列表中当前位置变化时都会发射currentIndexChanged()信号。

  QMediaPlaylist中的setPlaybackMode()可以设置播放模式,由QMediaPlaylist::PlaybackMode枚举类型进行定义,一共包含5种:
在这里插入图片描述

  QMediaPlaylist类为QMediaPlayer提供了一个内部的播放列表,但是其并非可视化部件,所以在实际应用中还需要将其可视化。

下面接着向前面的程序中添加代码,首先在mainwindow.h文件中添加前置声明:

class QMediaPlaylist;

然后添加一个私有播放列表对象:

QMediaPlaylist * playlist;

  下面进入mainwindow.cpp文件,先添加头文件,然后在构造函数最后添加如下代码:

playlist = new QMediaPlaylist;	// 调用无参构造函数,等价于new QMediaPlaylist()
playlist->addMedia(QUrl::fromLocalFile("../myplayer/music/G.E.M. 邓紫棋 - 泡沫.mp3"));
playlist->addMedia(QUrl::fromLocalFile("../myplayer/music/S.H.E - 不想长大 (Live).mp3"));
playlist->addMedia(QUrl::fromLocalFile("../myplayer/music/阿肆 - 我在人民广场吃炸鸡.mp3"));
playlist->setCurrentIndex(0);
playlist->setPlaybackMode(QMediaPlaylist::Loop);
player->setPlaylist(playlist);

另外,既然使用播放列表,那么就要把用于播放单个音乐的

player->setMedia(QUrl::fromLocalFile("C:/Users/25832/Documents/Qt-creator-pro/Media/myplayer/myplayer/music/郝云 - 活着.mp3"));

这句删掉。
在这里插入图片描述

这个程序运行时会连续循环播放几首音乐。


  Qt多媒体模块不仅对音频播放提供了强大的支持,而且对音视频录制和处理也提供了众多接口。

使用相机

  Qt多媒体模块中提供了一些与相机相关的类,如果设备安装了摄像头,那么就可以通过这些类进行拍照或者视频录制。

相机 QCamera

  可以使用QCameraInfo来查询系统当前可用的相机设备,一般使用其静态函数defaultCamera()来获取默认相机的设备信息,或者使用静态函数availableCameras()来获取所有可用的列表。例如:

QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
foreach(const QCameraInfo &cameraInfo, camera)
	qDebug() << cameraInfo.deviceName();

  这里的deviceName()可以返回相机的设备名称,它是相机的唯一ID,不过因为它是一串杂乱的编码,所以并不具有可读性。如果要获取友好的可读信息,则可以使用description(),它可以返回相机的描述,类似"USB 2.0 Camera"这样的信息,而且操作系统也经常通过这串字符来显示设备标题。用orientation()可以获取相机的旋转角度,这个一般只在移动设备上有效。

获取了可用的相机信息cameraInfo后,可以通过它来构建一个QCamera对象:

camera = new QCamera(cameraInfo);

  QCamera类为系统相机设备提供了相应的接口,可以使用start()和stop()来开启和关闭相机。相机拥有8种不同的状态。如下表所示,每当状态改变时都会发射statusChanged()信号。
在这里插入图片描述

  相机还支持曝光锁定,白平衡锁定和对焦锁定,由QCamera::LokType枚举类型定义,二者对应的值分别是QCamera::LockExposure,QCamera::LockWhiteBalance和QCamera::LockFocus,默认值是QCamera::NoLock(即不进行锁定)。可以通过supportLocks()来获取相机支持的锁定类型,使用searchAndLock()来设置锁定,使用unlock()来取消锁定。

  可以使用setViewfinder()来设置取景器部件。相机的取景器有两种选择,在普通部件中使用,可以使用QCameraViewfinder类,它继承自QVideoWidget;在图形视图框架中使用时,可以使用QGraphicsVideoItem类。

  通过setCaptureMode()可以设置相机的捕获模式,通过QCamera:CaptureModes枚举类型定义了3种捕获模式,默认的是QCamera::CaptureViewfinder模式,捕获的图像只显示在取景器上;QCamera::CaptureStillImage模式会进行静态帧捕获,也就是进行拍照;QCamera::CaptureVideo模式进行视频捕获,也就是录像。

猜你喜欢

转载自blog.csdn.net/qq_39153720/article/details/122118347