Qt知识回顾(十二)——音视频播放

  Qt对音视频的播放和控制、相机拍照、收音机等多媒体应用提供了强大的支持。Qt5使用了全新的Qt Multimedia模块来实现多媒体应用,Qt4用来实现多媒体功能的Phonon模块已经被移除。新的Qt Multimedia模块提供了丰富的接口,使读者可以轻松的使用平台的多媒体功能,例如,进行媒体播放、使用相机和收音机等。该模块分别提供了一组QML类型和一组C++类来处理多媒体内容。
  C++中多媒体模块可以实现的功能、对应的示例程序以及需要使用的C++类如下表所示:

功能示例C++类
播放音效QSoundEffect
播放低延迟音频audioinput,spectrumQAudioOutput
播放编码音频(MP3、AAC)playerQMediaPlayer
访问原始音频输入数据spectrum,audioinputQAudioInput
录制原始音频输入数据audiorecorderQAudioRecorder
发现原始音频设备audiodevicesQAudioDeviceInfo
播放视频playerQMediaPlayer、QVideoWidget、QGraphicsVideoItem
处理视频QMediaPlayer、QAbstractVideoSurface、QVideoFrame
收听录音机QRadioTuner、QRadioData
访问相机取景器cameraQCamera、QVideoWidget、QGraphicsVideoItem
处理取景器QCamera、QAbstractVideoSurface、QVideoFrame
拍摄照片cameraQCamera、QCameraImageCapture
拍摄视频cameraQCamera、QMediaRecorder

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

QT += multimedia

播放音频

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

播放压缩音频
  Qt中播放一个音频文件(比如MP3歌曲)十分简单,通过使用QMediaPlayer,只需要几行代码即可完成。QMediaPlayer被设计用来进行媒体播放,可以播放音频、视频和网络广播等。使用QMediaPlayer类播放音频的示例如下:

player = new QMediaPlayer;
player->setMedia(QUrl::fromLocalFile("/Users/lcc/Music/The Rain.mp3"));
player->play();

  可以看到,当创建QMediaPlayer后,只需要设置媒体源即可进行播放。这里使用了本地的一个MP3文件;若要播放网络歌曲,则只需要将地址修改为QUrl网络地址即可。QMediaPlayer支持的音频文件格式取决于操作系统环境以及用户安装的媒体插件。

低延迟声音效果
  QSoundEffect类可以使用一种低延迟方式来播放未压缩的音频文件,如WAV文件,它非常适合播放与用户交互时的音效,如弹出框提示因、虚拟键盘按键音、游戏音效等。如果并不需要低延迟效果,那么最好使用QMediaPlayer来播放音频,因为其支持更多的媒体格式并且占用资源更少。

effect = new QSoundEffect(this);
effect->setSource(QUrl::fromLocalFile("C:/Users/11830/Downloads/Michael Jackson - Earth Song.wav"));
effect->setVolume(0.25f);//设置音量大小
effect->play();//播放音乐
effect->setLoopCount(1);设置声明播放的次数
effect->stop();//暂停音乐

播放视频

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

播放视频文件
  视频文件可以通过QMediaPlayer进行播放,但是要在界面上显示视频内容,需要借助QVideoWidget或者QGraphicsVideoItem类,这两个类都属于Qt MulimediaWidgets模块。QVideoWidget继承自QWidget,所以它可以作为一个普通窗口部件进行显示,也可以嵌入到其他窗口中。将QVideoWidget指定为QMediaPlayer的视频输出窗口后,就可以显示播放的视频画面;当然,如果不为播放器设置视频输出界面,播放器也可以播放视频,不过只有声音而不会显示图像。使用QVideoWidget可以设置视频的亮度、对比度、色相和饱和度,还可以设置全屏显示,并且为这些功能设置了相应的信号和槽。
例子如下:
  新建Qt Widgets应用,名称为myvideowidget,基类选择QWidget,完成后在.pro文件中加入代码:QT += multimedia multimediawidgets,然后到.h头文件中添加类的前置声明:class QMediaPlayer; class QVideoWidget;然后添加私有对象:QMediaPlayer *player; QVideoWidget *videoWidget;
  进入设计模式,然后往界面上拖入4个标签Label和4个水平滑块Horizontal Slider,分为4组,将4个标签分别设置为亮度、对比度、色相和饱和度,而对应的滑块的objectName分别设置为brightnessSlider、contrastSlider、hueSlider和saturationSlider。最后将四个滑块的minimum属性设置为-100,maximum属性设置为100.
  然后进入.cpp文件,先添加头文件:#include<QMediaPlayer> #include<QVideoWidget>,然后在构造函数中添加如下代码:

 ui->setupUi(this);
    player = new QMediaPlayer(this);
    videoWidget = new QVideoWidget(this);

    videoWidget->resize(600,300);
    player->setVideoOutput(videoWidget);
    player->setMedia(QUrl::fromLocalFile("C:/Users/11830/Downloads/1.mp4"));
    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->contrast());
    connect(ui->saturationSlider,&QSlider::sliderMoved,videoWidget,&QVideoWidget::setSaturation);
    connect(videoWidget,&QVideoWidget::saturationChanged,ui->saturationSlider,&QSlider::setValue);

使用QMovie播放GIF文件
  QMovie类不属于多媒体模块,而是包含在Qt GUI模块中。QMovie使用QImageReader来播放没有声音的动画,比如GIF格式的文件,其支持的格式可以使用QMovie::supportedFormats()静态函数获取。要播放一个动画,只需要先创建一个QMovie对象,并为其指定要播放的动画文件,然后将QMovie对象传递给QLabel::setMovie()函数,最后调用start()函数来播放动画,例如:

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

  还可以使用setPaused(true)来暂停动画的播放,使用stop()函数可以停止动画的播放。QMovie一共有3个状态,如下表所示,每当状态改变时都会发射startChanged()信号,可以关联这个信号来改变播放、暂停等按钮。

常量描述
QMovie::NotRunning动画未执行。这是QMovie的初始状态,如果调用了stop()函数或者动画已经结束,则会进入该状态
QMovie::Paused动画被暂停,调用setPaused(true)函数后进入该状态,且保持当前的帧号,调用setPaused(false)函数后会继续播放下一帧
QMovie::Running动画正在播放

  可以使用frameCount()函数来获取当前动画的总的帧数;currentFrameNumber()函数可以返回当前帧堵塞序列号,动画第一帧的序列号为0,如果动画播放到了一个新的帧,QMovie会发射updated()信号,这时可以使用currentImage()或者currentPixmap()函数来获取当前帧的一个副本。还可以使用setCacheMode()来设置QMovie的缓存模式,这里有两个选项:QMovie::CacheNone和QMovie::CacheAll,前者是默认的缓存模式,不缓冲任何帧;后者是缓存所有的帧。如果指定了QMovie::CacheAll选项,那么就可以使用setSpeed()来设置动画的播放速度,该速度是以原始速度的百分比来衡量的,默认的速度为100%。

QMediaPlayer

  要使用QMediaPlayer进行播放,需要先使用setMedia(const QMediaContent &media,QIODevice stream =0)槽来设置媒体源。其中,QMediaContent提供了对媒体源的访问,它包含了媒体源的URL和格式信息,一般对于本地媒体只需要指定路径即可,所以所像前面代码那样直接使用QUrl::fromLocalFile指定路径即可。如果这里提供了一个媒体流stream,那么将会直接从流中读取媒体数据而不用再对媒体进行解析。设置完媒体源以后,可以使用play()函数进行播放,使用pause()、stop()进行暂停和停止。可以通过duration()可以获得当前媒体的时长,position()可以获得当前的播放位置,单位均为毫秒。使用setPosition()可以跳转到一个播放点,通过关联positionChanged()信号可以随时获取播放进度。使用volume()可以获取当前的播放音量,其范围为0~100,setVolume()可以设置音量大小;而当音量改变时会发射volumeChanged()信号,如果要设置为静音,可以使用setMuted()函数。

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

常量描述
QMediaPlayer::UnknownMediaStatus媒体的状况无法确定
QMediaPlayer::NoMedia当前媒体不存在时,播放器处于停止状态
QMediaPlayer::LoadingMedia当前媒体正在被加载时,播放器可以处于任何状态
QMediaPlayer::LoadedMedia当前媒体已经加载完毕,播放器处于停止状态
QMediaPlayer::StalledMedia没有足够的缓冲或者其他临时中断,而导致当前媒体的播放处于停滞时,播放器处于播放状态或者暂停状态
QMediaPlayer::BufferingMedia播放器正在缓冲数据,但已经缓冲了足够的数据以便稍后后继续播放时,播放器处于播放状态或者暂停状态
QMediaPlayer::BufferedMedia播放器已经完全缓冲了当前媒体时,播放器处于播放状态或者暂停状态
QMediaPlayer::EndOfMedia已经播放到了当前媒体的结尾时,播放器处于停止状态
QMediaPlayer::InvalidMedia当前媒体无法播放时,播放器处于停止状态

  当播放器发生错误时会发射error()信号,通过关联该信号可以对相应的错误进行处理。播放器会出现6种不同的错误情况,这6种情况由QMediaPlayer::Error枚举类型定义,取值如下表:

常量描述
QMediaPlayer::NoError没有发生错误
QMediaPlayer::ResourceError媒体资源无法被解析
QMediaPlayer::FormatError媒体格式不(完全)支持,可能依然可以播放,但是会缺少声音或者图像
QMediaPlayer::NetworkError发生了一个网络错误
QMediaPlayer::AccessDeniedError没有相应的权限来播放媒体资源
QMediaPlayer::ServiceMissingError没有发现有效的播放服务,无法进行播放

  QMediaPlayer进行播放时拥有3种状态,他总是处于这3种状态的其中一种。这3种状态由QMediaPlayer::State枚举类型定义,器取值如下,无论其先前处于什么状态,当播放器的状态发生改变时就会发射stateChanged()信号,可以通过关联该信号来获取播放器当前的状态,从而进行一些有关的设置,比如更改播放控制图标等。

常量描述
QMediaPlayer::StoppedState停止状态。处于该状态时,播放器会从当前媒体的开始进行播放,调用stop()函数可以直接进入该状态
QMediaPlayer::PlayingState播放状态,媒体器正在播放媒体内容,调用play()函数可以进入该状态
QMediaPlayer::PausedState暂停状态,播放器暂时停止当前的播放。处于该状态时播放器会从当前媒体暂停的位置进行播放,调用pause()函数可以直接进入暂停状态

获取媒体元数据
  可以使用QMediaPlayer的metaData()函数来获取媒体的元数据。QMediaMetaData命名空间中提供了众多元数据属性,例如,标题Title、作者Author、长度Duration等,每当QMediaPlayer对媒体源进行解析,元数据可用时都会发射metaDataAvailableChanged()信号,可以关联该信号来获取当前媒体的相关信息。

播放列表
  QMediaPlaylist类提供了一个播放列表,它其实是一个QMediaContent对象列表,并且包含了一些使用功能,QMediaPlayer可以通过setPlaylist()来设置一个播放里欸包。QMediaPlaylist可以通过addMedia()来添加一个QMediaContent对象或者添加一个QMediaContent对象列表作为媒体源,也可以通过insertMedia()将媒体插入到列表任意位置,或者使用load()函数来加载网络资源。使用mediaCount()可以获取列表中媒体的数量,currentMedia()可以获取当前的媒体。使用removeMedia()可以设置删除一个媒体,而clear()可以清空整个播放列表。可以通过next()、previous()、setCurrentIndex()、shuffle()等槽来指定播放列表中的条目进行播放,每当播放列表中当前位置变化时都会发射currentIndexChanged()信号。QMediaPlaylist中的setPlatbackMode()可以设置播放模式,由QMediaPlaylist::playbackMode枚举类型进行定义,一共包含5种,如下表所示:

常量描述
QMediaPlaylist::CurrentItemOnce当前项只播放一次
QMediaPlaylist::CurrentItemInLoop当前项进行循环播放
QMediaPlaylist::Sequential默认值。从当前项开始顺序播放,直到列表最后一项播放结束后停止。最后一项的下一项为NULL
QMediaPlaylist::Loop播放完最后一项会从头开始循环播放
QMediaPlaylist::Random随机播放
  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值