36. 媒体录制
一、多媒体设备
多媒体设备是指本机中的音频输入设备(如麦克风)、音频输出设备(如音箱、头戴耳机)和视频输入设备(如摄像头)。多媒体设备 通过 QMediaDevices 类提供的方法来获取,音频输入输出设备类 是 QAudioDevice,视频输入设备类 是 QCameraDevice。
我们可以在终端中使用 pip 安装 PySide6 模块。默认是从国外的主站上下载,因此,我们可能会遇到网络不好的情况导致下载失败。我们可以在 pip 指令后通过 -i 指定国内镜像源下载。
pip install pyside6 -i https://mirrors.aliyun.com/pypi/simple
国内常用的 pip 下载源列表:
- 阿里云 https://mirrors.aliyun.com/pypi/simple
- 清华大学 https://pypi.tuna.tsinghua.edu.cn/simple
- 中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple
用 QMediaDevices、QAudioDevice 和 QCameraDevice 创建设备实例的方法如下所示:
QMediaDevices(parent:QObject=None)
QAudioDevice()
QCameraDevice()
我们可以先用 QMediaDevices 提供的静态方法 获取本机上的音频设备和视频输入设备,然后再使用 QAudioDevice 和 QCameraDevice 提供的方法分别 获取音频设备和视频输入设备的详细信息。
QMediaDevices 类的常用方法如下:
# 静态方法
audioInputs() -> List[QAudioDevice] # 获取音频输入设备
defaultAudioInput() -> QAudioDevice # 获取默认音频输入设备
audioOutputs() -> List[QAudioDevice] # 获取音频输出设备
defaultAudioOutput() -> QAudioDevice # 获取默认音频输出设备
videoInputs() -> List[QCameraDevice] # 获取视频输入设备
defaultVideoInput() -> QCameraDevice # 获取默认的视频输入设备
QMediaDevices 类的信号方法如下:
audioInputsChanged() # 当音频输入设备发生改变时发射信号
audioOutputsChanged() # 当音频输出设备发生改变时发射信号
videoInputsChanged() # 当视频输入设备发生改变时发射信号
QAudioDevice 类的常用方法如下:
description() -> str # 获取音频设备的信息
id() -> QQByteArray # 获取音频设备的识别号
isDefault() -> bool # 获取是否是默认的音频设备
isFormatSupported(format:QAudioFormat) -> bool # 获取音频设备是否支持某种音频格式
isNull() -> bool # 获取设备是否有效
minimumChannelCount() -> int # 获取音频设备支持的最小通道数
maximumChannelCount() -> int # 获取音频设备支持的最大通道数
minimumSampleRate() -> int # 获取音频设备支持的最小采样率
maximumSampleRate() -> int # 获取音频设备支持的最大采样率
mode() -> QAudioDevice.Mode # 获取音频设备是输入还是输出设备
preferredFormat() -> QAudioFormat # 获取音频设备的默认音频格式
supportedSampleFormats() -> List[QAudioFormat.SampleFormat] # 获取音频设备支持的采样格式
mode() 的方法 获取音频设备是输入还是输出设备,返回值是 QAudioDevice.Mode 类型的枚举值,返回的值可以是:
QAudioDevice.Mode.Null # 无效设备
QAudioDevice.Mode.Input # 输入设备
QAudioDevice.Mode.Output # 输出设备
supportedSampleFormats() 方法 获取音频设备支持的采样格式,返回值是 QAudioFormat.SampleFormat 类型的列表,QAudioFormat.SampleFormat 枚举值如下:
QAudioFormat.SampleFormat.UInt8
QAudioFormat.SampleFormat.Int16
QAudioFormat.SampleFormat.Int32
QAudioFormat.SampleFormat.Float
QAudioFormat.SampleFormat.Unknown
QCameraDevice 类的常用方法如下:
description() -> str # 获取视频输入设备的信息
id() -> QQByteArray # 获取视频输入设备的识别号
isDefault() -> bool # 获取是否是默认的视频输入设备
isNull() -> bool # 获取视频输入设备是否有效
photoResolutions() -> List[QSize] # 获取视频输入设备的分辨率
position() -> QCameraDevice.Position # 获取视频输入的位置
videoFormats() -> List[QCameraFormat] # 获取视频输入设备支持的格式
position() 方法 获取视频输入的位置,返回值是 QCameraDevice.Position 类型的枚举值,返回值可以是:
QCameraDevice.Position.BackFace # 后置摄像头
QCameraDevice.Position.FrontFace # 前置摄像头
QCameraDevice.Position.UnspecifiedPosition # 位置不确定
二、音频接口
要录制音频,需要定义音频设备的接口 QAudioInput ,才能调用音频设备进行录制。QAudioInput 是机器上的音频输入,例如内置麦克风或头戴麦克风。
用 QAudioInput 创建音频设备接口 的方法如下所示:
QAudioInput(parent:QObject=None)
QAudioInput(deviceInfo:QAudioDevice, parent:QObject=None)
音频接口 QAudioInput 类的常用方法如下:
# 实例方法
device() -> QAudioDeicve # 获取音频设备
isMuted() -> bool # 获取是否静音
volume() -> bool # 获取音量
# 槽函数
setDevice(device:QAudioDevice) -> None # 设置音频设备
setMuted(muted:bool) -> None # 设置是否静音
setVolume(volume:float) -> float # 设置音量
音频接口 QAudioInput 类的常用信号如下:
deviceChanged() # 当设备发生改变时发射信号
mutedChanged(muted:bool) # 当静音状态发生改变时发射信号
volumeChanged(volume:float) # 当音量发生改变时发射信号
三、视频接口
要录制视频,还需要定义视频设备的接口 QCamera ,才能调用音频设备和视频设备进行录制。QCamera 是机器上的摄像头或外接相机。
用 QCamera 创建视频设备接口 的方法如下所示:
QCamera(parent:QObject=None)
QCamera(position:QCameraDevice.Position, parent:QObject=None)
视频接口 QCamera 类的常用方法如下:
# 实例方法
setCameraDevice(cameraDevice:QCameraaDevice) -> None # 设置视频设备
cameraDevice() -> QCameraDevice # 获取视频设备
isActive() -> bool # 获取相机是否启用
isAvailable() -> bool # 获取相机是否可用
setCameraFormat(format:QCameraFormat) -> None # 设置视频格式
captureSession() -> QMediaCaptureSession # 获取与QCamera关联的媒体捕获器
supportedFeatures() -> QCamera.Features # 获取支持的特征
isExposureModeSupported(mode:QCamera.ExposureMode) -> None # 获取是否支持某种曝光
exposureTime() -> float # 获取曝光时间
manualExposureTime() -> float -> float # 获取自定义曝光时间
isoSensitivity() -> int # 获取光敏感值
exposureCompensation() -> float # 获取曝光补偿(EV值)
flashMode() -> QCamera.FlashMode # 获取快闪模式
isFlashModeSupported(mode:QCamera.FlashMode) -> bool # 获取是否支持某种快闪模式
isFlashReady() -> bool # 获取是否可以用快闪
setFocusMode(mode:QCamera.FocusMode) -> None # 设置对焦模式
isFlashModeSupported(mode:QCamera.FocusMode) -> bool # 获取是否支持某种焦点模式
setFocusDistance(d:float) -> None # 设置自定义焦距,0表示最近的点,1表示无限远
focusDistance() -> float # 获取自定义焦距
setCustomFocusPoint(point:Union[QPoint, QPointF]) -> None # 设置自定义焦点位置
customFocusPoint() -> QPointF # 获取自定义焦点
focusPoint() -> QPointF # 获取焦点
torchMode() -> QCamera.TorchMode # 获取辅助光源模式
isTorchModeSupported(mode:QCamera.TorchMode) -> bool # 获取是否支持某种辅助光源模式
whiteBalanceMode() -> QCamera.WhiteBalanceMode # 获取白平衡模式
isWhiteBalanceModeSupported(mode:QCamera.WhiteBalanceMode) -> bool # 获取是否支持某种白平衡模式
colorTemperature() -> int # 获取颜色温度
setZoomFactor(factor:float) -> None # 设置缩放系数
zoomFactor() -> float # 获取缩放系数
minimumExposureTime() -> float # 获取最小的曝光时间
maximumExposureTime() -> float # 获取最大的曝光时间
minimumIsoSensitivity() -> int # 获取最小的光敏感值
maximumIsoSensitivity() -> int # 获取最大的光敏感值
minimumZoomFactor() -> float # 获取最小的方法系数
maximumZoomFactor() -> float # 获取最大的放大系数
error() -> QCamera.Error # 获取出错类型
errorString() -> str # 获取出错信息
# 槽函数
start() -> None # 开启相机
stop() -> None # 关闭相机
setActive(active:bool) -> None # 获取相机是否启用
setExposureMode(mode:QCamera.ExposureMode) -> None # 设置曝光模式
setAutoExposureTime() -> None # 打开自动计算曝光时间
setManualExposureTime(seconds:float) -> None # 设置曝光时间
setAutoIsoSensitivity() -> None # 根据曝光值开启自动选择光敏感值
setExposureCompensation(ev:float) -> None # 设置曝光补偿(EV值)
setFlashMode(mode:QCamera.FlashMode) -> bool # 设置是否可以用快闪
setTorchMode(mode:QCamera.TorchMode) -> None # 设置辅助光源模式
setWhiteBalanceMode(mode:QCamera.WhiteBalanceMode) -> None # 设置白平衡模式
setColorTemperature(colorTemperature:int) -> None # 设置颜色温度
zoomTo(zoom:float, rate:float) -> None # 根据速率设置缩放系数
视频接口 QCamera 类的常用信号如下:
activeChanged(active:bool) # 照相机启动或停止时发射信号
cameraDeviceChanged() # 照相设备发生改变时发射信号
cameraFormatChanged() # 格式发生改变时发射信号
focusModeChanged() # 焦点模式发生改变时发射信号
focusDistanceChanged(d:float) # 焦距发生改变时发射信号
focusPointChanged() # 聚焦点发生改变时发射信号
customFocusPointChanged() # 自定义聚焦点发生改变时发射信号
exposureModeChanged() # 曝光模式发生改变时发射信号
exposureCompensationChanged(value:float) # 曝光补偿发生改变时发射信号
exposureTimeChanged(speed:float) # 曝光时间发生改变时发射信号
manualExposureTimeChanged(speed:float) # 自动曝光时间发生改变时发射信号
flashModeChanged() # 快闪模式发生改变时发射信号
flashReady(ready:bool) # 可以快闪时发射信号
isoSensitivityChanged(value:int) # 光敏感值发生改变时发射信号
manualIsoSensitivityChanged(value:int) # 自定义光敏感值发生改变时发射信号
minimumZoomFactorChanged(value:float) # 最小缩放系数发生改变时发射信号
maximumZoomFactorChanged(value:float) # 最大缩放系数发生改变时发射信号
zoomFactorChanged(value:int) # 缩放系数发生改变时发射信号
saturationChanged()
supportedFeaturesChanged() # 支持的功能发生改变时发射信号
torchModeChanged() # 辅助光源模式发生改变时发射信号
whiteBalanceModeChanged() # 白平衡模式发生改变时发射信号
colorTemperatureChanged() # 色温发生改变时发射信号
errorChanged() # 错误状态发生改变时发射信号
errorOccurred(error:QCamera.Error, errorString:str) # 出现错误时发射信号
用 setCameraDevice(cameraDevice:QCameraDevice) 方法 为视频接口设置视频设备。用 start() 方法或 setActive(true) 方法 开启视频设备。用 stop() 方法或 setActive(false) 方法 停止视频设备。
用 supportedFeatures() 方法 获取相机支持的特征,返回值是 QCamera.Feature 类型的枚举值,可能的取值如下所示:
QCamera.Feature.ColorTemperature # 相机支持色温
QCamera.Feature.ExposureCompensation # 相机支持补偿曝光
QCamera.Feature.IsoSensitivity # 相机支持自定义敏感值
QCamera.Feature.ManualExposureTime # 相机支持自定义曝光时间
QCamera.Feature.CustomFocusPoint # 相机支持自定义焦点
QCamera.Feature.FocusDistance # 相机支持自定义焦距
用 setExposureMode(mode:QCamera.ExposureMode) 方法 设置相机的曝光模式,参数 mode 是 QCamera.ExposureMode 的枚举值,可取的值如下所示;
QCamera.ExposureMode.ExposureAuto # 自动
QCamera.ExposureMode.ExposureManual # 手动
QCamera.ExposureMode.ExposurePortrait # 人物
QCamera.ExposureMode.ExposureNight # 夜晚
QCamera.ExposureMode.ExposureSports # 运动
QCamera.ExposureMode.ExposureSnow # 雪景
QCamera.ExposureMode.ExposureBeach # 海景
QCamera.ExposureMode.ExposureAction # 动作
QCamera.ExposureMode.ExposureLandscape # 风景
QCamera.ExposureMode.ExposureNightPortrait # 夜晚
QCamera.ExposureMode.ExposureTheatre # 剧院
QCamera.ExposureMode.ExposureSunset # 傍晚
QCamera.ExposureMode.ExposureSteadyPhoto # 固定
QCamera.ExposureMode.ExposureFireworks # 火景
QCamera.ExposureMode.ExposureParty # 宴会
QCamera.ExposureMode.ExposureCandlelight # 烛光
QCamera.ExposureMode.ExposureBarcode # 条码
用 setFlashMode(mode:QCamera.FlashMode) 方法 设置相机的快闪模式,参数 mode 是 QCamera.FlashMode 的枚举值,可取值如下:
QCamera.FlashMode.FlashOff
QCamera.FlashMode.FlashOn
QCamera.FlashMode.FlashAuto
用 setFocusMode(mode:QCamera.FocusMode) 方法 设置对焦模式,参数 mode 的取值是 QCamera.FocusMode 的枚举值,可取的值如下所示:
QCamera.FocusMode.FocusModeAuto # 连续自动对焦模式
QCamera.FocusMode.FocusModeAutoNear # 对近处物体连续自动对焦模式
QCamera.FocusMode.FocusModeAutoFar # 对远处物体连续自动对焦模式
QCamera.FocusMode.FocusModeHyperfocal # 对超过焦距范围的物体采用最大景深值
QCamera.FocusMode.FocusModeInfinity # 对无限远对焦模式
QCamera.FocusMode.FocusModeManual # 手动或固定对焦模式
用 setTorchMode(mode:QCamera.TorchMode) 方法 设置辅助光源模式,在光线不强时可以设置该模式,并会覆盖快闪模式,参数 mode 是 QCamera.TorchMode 类型的枚举值,可取值如下:
QCamera.TorchMode.TorchOff
QCamera.TorchMode.TorchOn
QCamera.TorchMode.TorchAuto
用 setWhiteBalanceMode(mode:QCamera.WhiteBalanceMode) 方法 设置白平衡模式,白平衡是描述红、绿、蓝三基色混合生成后白色精确度的一项指标。在房间里的日光灯下拍摄的影像会显得发绿,在室内钨丝灯光下拍摄出来的景物会偏黄,而在日光阴影处拍摄到的照片则偏蓝,白平衡的作用是不管在任何光源下都能将白色物体还原为白色。参数 mode 是 QCamera.WhiteBalanceMode 的枚举值,可取的值如下所示:
QCamera.WhiteBalanceMode.WhiteBalanceAuto # 自动
QCamera.WhiteBalanceMode.WhiteBalanceManual # 手动
QCamera.WhiteBalanceMode.WhiteBalanceShade # 阴影
QCamera.WhiteBalanceMode.WhiteBalanceTungsten # 钨灯
QCamera.WhiteBalanceMode.WhiteBalanceFluorescent # 荧光灯
QCamera.WhiteBalanceMode.WhiteBalanceSunlight # 阳光
QCamera.WhiteBalanceMode.WhiteBalanceCloudy # 云
QCamera.WhiteBalanceMode.WhiteBalanceFlash # 快闪
QCamera.WhiteBalanceMode.WhiteBalanceSunset # 日落
在手动模式下,需要用 setColorTemperature(colorTemperature:int) 方法 设置色温。
四、媒体捕获器
媒体捕获器 QMediaCaptureSession 是音频数据和视频数据的集散地,它接收从 QAudioInput 和 QCamera 传递过来的音频和视频,然后将音频转发给 QAudioOutput 播放音频,将视频转发给 QVideoWidegt 或 QGraphicsVideoItem 播放视频,或者将音频和视频转发给 QMdiaRecorder 录制音频和视频,转发给 QImageCapture 实现拍照功能。
用 QMediaCaptureSession 创建实例对象的方法如下所示:
QMediaCaptureSession(parent:QObject=None)
QMediaCaptureSession 类的常用方法如下:
setAudioInput(input:QAudioInput) -> None # 设置音频输入
audioInput() -> QAudioInput # 获取音频输入
setAudioOutput(output:QAudioOutput) -> None # 设置音频输出
audioOutput() -> QAudioOutput # 获取音频输出
setCamera(camera:QCamera) -> None # 设置视频接口
camera() -> QCamera # 获取视频接口
setVideoOutput(output:QObject) -> None # 设置视频输出
videoOutput() -> QObject # 获取视频输出
setVideoSink(sink:QVideoSink) -> None # 设置视频接收器
videoSink() -> QVideoSink # 获取视频接收器
setImageCapture(imageCapture:QImageCapture) -> None # 设置图像捕获器
imageCapture() -> QImageCapture # 获取图像捕获器
setRecorder(recorder:QMidiaRecorder) -> None # 设置媒体记录器
recorder() -> QMeidaRecorder # 获取媒体记录器
QMediaCaptureSession 类的常用信号如下:
audioInputChanged() # 当音频输入发生改变时发射信号
audioOutputChanged() # 当视频输出发生改变时发射信号
cameraChanged() # 当视频输入发生改变时发射信号
videoOutputChanged() # 当视频输出发生改变时发射信号
imageCaptureChanged() # 当图像捕获器发生改变时发射信号
screenCaptureChanged() # 当屏幕捕获器发生改变时发射信号
windowCaptureChanged() # 当窗口捕获器发生改变时发射信号
recorderChanged() # 当记录器发生改变时发射信号
新建一个 ui.py 文件,用来存放 UI 相关的代码。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QToolBar
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtGui import Qt, QIcon
from PySide6.QtMultimediaWidgets import QVideoWidget
class MyUi:
def setupUi(self, window:QWidget):
window.resize(800, 600) # 1.设置窗口对象大小
layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.toolBar = QToolBar() # 3.创建一个工具栏,并添加到布局中
layout.addWidget(self.toolBar)
self.toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # 4.设置工具栏的显示样式
# 5.往工具栏中添加动作
self.open_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "打开摄像头")
self.close_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "关闭摄像头")
self.videoWidget = QVideoWidget() # 6.创建显示视频的控件,并添加到布局中
layout.addWidget(self.videoWidget)
新建一个 widget.py 文件,用来存放业务逻辑相关的代码。
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtMultimedia import QMediaDevices, QCamera, QMediaCaptureSession
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.mediaDevice = QMediaDevices(self) # 3.创建媒体设备
self.cameraDevice = self.mediaDevice.defaultVideoInput() # 4.获取默认的视频输入设备
self.camera = QCamera(self.cameraDevice) # 5.根据视频输入设备定义视频接口
self.mediaCaptureSession = QMediaCaptureSession(self) # 6.创建媒体捕获器
self.mediaCaptureSession.setCamera(self.camera) # 7.设置设备媒体捕获器的视频接口
self.mediaCaptureSession.setVideoOutput(self.__ui.videoWidget) # 8.设置媒体捕获器的视频输出控件
# 9.动作被触发时发送信号
self.__ui.open_action.triggered.connect(self.camera.start)
self.__ui.close_action.triggered.connect(self.camera.stop)
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
五、媒体格式
在进行音频和视频的录制时,需要指定音频和视频的记录格式,以及媒体文件的存储格式,这些格式通过 QMediaFormat 类来定义。
用 QMediaFormat 类创建媒体格式实例的方法如下所示:
QMediaFormat(format:QMediaFormat.FileFormat=QQMediaFormant.UnspecifiedFormat)
QMediaFormat(other:Union[QMediaFotmat, QMediaFotmant.FileFormat])
QMediaFormat 类的常用方法如下:
# 实例方法
setFileFormat(format:QMediaFormat.FileFormat) -> None # 设置文件格式
fileFormat() -> QMediaFormat.FileFormat # 获取文件格式
setAudioCodec(codec:QMediaFormat.AudioCode) -> None # 设置音频编码格式
audioCodec() -> QMediaFormat.AudioCodec # 获取音频编码格式
setVideoCodec(codec:QMediaFormat.VideoCodec) -> None # 设置视频编码格式
videoCodec() -> QMediaFormat.VideoCodec # 获取视频编码格式
supportedFileFormats(mode:QMediaFormat.ConversionMode) -> list[QMediaFormat.FileFormat] # 获取支持的文件编码格式列表
supportedAudioCodecs(mode:QMediaFormat.ConversionMode) -> list[QMediaFormat.AudioCode] # 获取支持的音频编码格式列表
supportedVideoCodecs(mode:QMediaFormat.ConversionMode) -> list[QMediaFormat.VideoCode] # 获取支持的视频编码格式列表
isSupported(mode:QMediaFormat.ConversionMode) -> bool # 获取是否可以对某种编码格式编码或解码
# 静态方法
fileFormatName(fileFormat:QMediaFormat.FileFormat) -> str # 获取文件格式名称
fileFormatDescription(fileFormat:QMediaFormat.FileFormat) -> str # 获取文件格式信息
audioCodecName(codec:QMediaFormat.AudioCode) -> str # 获取音频格式名称
audioCodecDescription(codec:QMediaFormat.AudioCode) -> str # 获取音频格式信息
videoCodecName(codec:QMediaFormat.VideoCode) -> str # 获取视频格式名称
videoCodecDescription(codec:QMediaFormat.VideoCode) -> str # 获取视频格式信息
分别用 supportedFileFormats(mode:QMediaFormat.ConversionMode) 方法、supportedAudioCodecs(mode:QMediaFormat.ConversionMode) 方法和 supportedVideoCodecs(mode:QMediaFormat.ConversionMode) 方法 获取编码或解码时支持的文件格式列表、音频编码格式列表和视频编码格式列表,参数 mode 是 QMediaFormat.ConversionMode 类型的枚举值,可取值如下:
QMediaFormat.ConversionMode.Encode
QMediaFormat.ConversionMode.Decode
六、图像捕获
用媒体捕获器 QMediaCaptureSession 的 setImageCapture(imageCapture:QImageCapture) 方法将 QImageCapture 与 QMediaCatureSession 关联,可以捕获图像,实现拍照功能。
用 QImageCapture 类定义图像捕获的方法如下所示:
QImageCapture(parent:QObject=None)
QImageCapture 类常用方法如下:
# 实例方法
isReadyForCapture() -> bool # 获取是否可以拍照
captureSession() -> QMediaCaptureSession # 获取关联的捕捉器
setFileFormat(format:QImageCapture.FileFormat) -> None # 设置文件格式
fileFormat() -> QImageCapture.FileFormat # 获取文件格式
setQuality(quality:QImageCapture.Quality) -> None # 设置图像质量
quality() -> QImageCapture.Quality # 获取图像质量
setResolution(size:QSize) -> None # 设置分辨率
setResolution(width:int, height:int) -> None # 设置分辨率
resolution() -> QSize # 获取分辨率
setMetaData(metaData:QMediaMetaData) -> None # 设置元数据
metaData() -> QMediaMetaData # 获取元数据
addMetaData(metaData:QMediaMetaData) -> None # 添加元数据
error() -> QImageCapture.Error # 获取出错信息
errorString() -> str # 获取出错信息
# 槽函数
capture() -> int # 进行拍照
captureToFile(location="") -> int # 拍照到文件
# 静态方法
fileFormatDescription(c:QImageCapture.FileFormat) -> str # 获取格式的信息
fileFormatName(c:QImageCapture.FileFormat) -> str # 获取格式的名称
supportedFormats() -> List[QImageCapture.FileFormat] # 获取支持的格式
QImageCapture 类常用信号如下:
readyForCaptureChanged(ready:bool) # 准备状态发生改变时发射信号
imageCaptured(id:int, preview:QImage) # 捕捉到图象时发射信号
imageExposed(id:int) # 图像曝光时发射信号
imageSaved(id:int, fileName:str) # 保存图像时发射信号
imageAvailable(id:int, frame:QVideoFrame) # 可以获取图像时发射信号
metaDataChanged() # 元数据发生改变时发射信号
qualityChanged() # 图像质量发生改变时发射信号
errorOccurred(id:int, error:QImageCapture.Error, errorString:str) # 出现错误时发射信号
errorChanged() # 错误状态发生改变时发射信号
fileFormatChanged() # 文件格式发生改变时发射信号
当 isReadyForCapture() 的返回值是 True 时,可以进行拍照。用 capture() 方法 进行拍照,返回值是拍照的识别号 ID,同时会发送 imageCaptured(id:int,preview:QImage) 信号和 imageExposed(id:int) 信号。
我们也可以用 captureToFile(location:str='') 方法 直接将拍摄的图像保存到文件中,同时发送 imageCaptured(id:int, preview:QImage) 信号、imageExposed(id:int) 信号和 imageSaved(id:int,fileName:str) 信号,如果没有给出保存的文件名和路径,则使用默认的路径和文件名,如果只给出文件名,则保存到默认路径下,完整路径可以通过 imageSaved(id:int, fileName:str) 信号的参数获取。
用 error() 方法 获取拍照时的出错状态,返回值是 QImageCapture.Error 类型的枚举值,可能取值如下:
QImageCapture.Error.NoError # 没有错误
QImageCapture.Error.NotReadyError # 设备没准备好
QImageCapture.Error.ResourceError # 设备没准备好或不可用
QImageCapture.Error.OutOfSpaceError # 存储空间不够
QImageCapture.Error.NotSupportedFeatureError # 设备不支持拍照
QImageCapture.Error.FormatError # 格式出错
用 setFileFormat(format:QImageCapture.FileFormat) 方法 设置拍照的格式,参数 format是 QImageCapture.FileFormat 类型的枚举值,可以取值如下:
QImageCapture.FileFormat.JPEG
QImageCapture.FileFormat.PNG
QImageCapture.FileFormat.Tiff
QImageCapture.FileFormat.WebP
QImageCapture.FileFormat.UnspecifiedFormat
QImageCapture.FileFormat.LastFileFormat
用 setQuality(quality:QImageCapture.Quality) 方法 设置图像质量,参数 quality 是 QImageCapture.Quality 类型的枚举值,可以取值如下:
QImageCapture.Quality.VeryLowQuality
QImageCapture.Quality.LowQuality
QImageCapture.Quality.NormalQuality
QImageCapture.Quality.HighQuality
QImageCapture.Quality.VeryHighQuality
其中 imageAvailable(id:int, frame:QVideoFrame) 信号的参数 frame 是视频帧,利用 QVideoFrame 的 toImage() 方法可以得到 QImage。
修改 ui.py 文件的内容。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QToolBar
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtGui import Qt, QIcon
from PySide6.QtMultimediaWidgets import QVideoWidget
class MyUi:
def setupUi(self, window:QWidget):
window.resize(800, 600) # 1.设置窗口对象大小
layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.toolBar = QToolBar() # 3.创建一个工具栏,并添加到布局中
layout.addWidget(self.toolBar)
self.toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # 4.设置工具栏的显示样式
# 5.往工具栏中添加动作
self.camera_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "打开摄像头")
self.take_photo_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "拍照")
self.videoWidget = QVideoWidget() # 6.创建显示视频的控件,并添加到布局中
layout.addWidget(self.videoWidget)
修改 widget.py 文件的内容。
import sys
import os
import time
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtMultimedia import QMediaDevices, QCamera
from PySide6.QtMultimedia import QMediaCaptureSession, QImageCapture
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.mediaDevice = QMediaDevices(self) # 3.创建媒体设备
self.cameraDevice = self.mediaDevice.defaultVideoInput() # 4.获取默认的视频输入设备
self.camera = QCamera(self.cameraDevice) # 5.根据视频输入设备定义视频接口
self.mediaCaptureSession = QMediaCaptureSession(self) # 6.创建媒体捕获器
self.mediaCaptureSession.setCamera(self.camera) # 7.设置设备媒体捕获器的视频接口
self.mediaCaptureSession.setVideoOutput(self.__ui.videoWidget) # 8.设置媒体捕获器的视频输出控件
# 9.动作被触发时发送信号
self.__ui.camera_action.triggered.connect(self.camera_action)
self.__ui.take_photo_action.triggered.connect(self.take_photo)
def camera_action(self):
if self.__ui.camera_action.text() == "打开摄像头":
self.camera.start() # 1.打开摄像头
self.__ui.camera_action.setText("关闭摄像头") # 2.摄像头操作按钮文本显示为关闭摄像头
self.imageCapture = QImageCapture() # 3.创建图片捕获对象,并关联摄像头
self.imageCapture.setFileFormat(QImageCapture.FileFormat.JPEG) # 4.设置图像图示
self.imageCapture.setResolution(1920, 1080) # 5.设置分辨率
self.imageCapture.setQuality(QImageCapture.Quality.HighQuality) # 6.设置图片质量
self.mediaCaptureSession.setImageCapture(self.imageCapture) # 7.设置捕获器
elif self.__ui.camera_action.text() == "关闭摄像头":
self.camera.stop() # 8.关闭摄像头
self.__ui.camera_action.setText("打开摄像头") # 9.摄像头操作按钮文本显示为打开摄像头
self.imageCapture = None # 10.图片捕获对象设置为空
def take_photo(self):
if self.imageCapture:
file_name = f"{os.getcwd()}/{time.strftime('%Y%m%d%H%M%S', time.localtime())}.jpeg"
self.imageCapture.captureToFile(file_name) # 1.拍照到文件
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束
七、媒体录制
QMediaRecorder 可以录制从 QMediaCaptureSession 获取的音频和视频,并对音频和视频进行编码,需要用 QMediaCaptureSession 的 setRecorder(recorder:QMediaRecorder) 方法 设置关联的捕获器。
用 QMediaRecorder 创建实例的方法如下所示:
QMediaRecorder(parent:QObject=None)
QMediaRecorder 类的常用方法如下:
# 实例方法
isAvailable() -> bool # 获取是否可以录制
duration() -> int # 获取录制时间
recorderState() -> QMediaRecorder.recorderState # 获取录制状态
error() -> QMediaRecorder.Error # 获取出错内容
errorString() -> str # 获取错误信息
setAudioBitRate(bitRate:int) -> None # 设置音频比特率
audioBitRate() -> int # 获取音频比特率
setAudioChannelCount(channels:int) -> None # 设置音频通道数
audioChannelCount() -> int # 获取音频通道数
setAudioSampleRate(sampleRate:int) -> None # 设置音频采样率
audioSampleRate() -> int # 获取音频采样率
setEncodingMode(mode:QMediaRecorder.EncodingMode) -> None # 设置编码格式
encodingMode() -> QMeidaRecorder.encodingMode # 获取编码格式
setMediaFormat(format:Union[QMediaFormat, QMediaFormat.FileFotmat]) -> None # 设置媒体格式
setQuality(quality:QMediaRecorder.Quality) -> None # 设置录制质量
quality() -> QMediaRecorder.Quality # 获取录制质量
setVideoBitRate(bitRate:int) -> None # 设置视频比特率
videoBitRate() -> int # 获取视频比特率
setVideoFrameRate(frameRate:float) -> None # 设置视频帧速
videoFrameRate() -> float # 获取视频帧速
setVideoResolution(size:QSize) -> None # 设置视频分辨率
setVideoResolution(width:int, height:int) -> None # 设置视频分辨率
videoResolution() -> QSize # 获取视频分辨率
setMetaData(metaData:QMediaMetaData) -> None # 设置媒体元数据
metaData() -> QMediaMeta # 获取媒体元数据
addMetaData(metaData:QMediaMetaData) -> None # 添加媒体元数据
setOutputLocation(location:QUrl) -> None # 设置媒体输出位置
outputLocation() -> QUrl # 获取输出位置
actualLocation() -> QUrl # 获取实际的输出位置
# 槽方法
record() -> None # 开始录制
pause() -> None # 暂停录制
stop() -> None # 停止录制
QMediaRecorder 类的常用信号如下:
actualLocationChanged(location:QUrl) # 存储位置发生改变时发射信号
durationChanged(duration:int) # 录制时间发生改变时发射信号
errorChanged() # 错误状态发生改变时发射信号
errorOccurred(error:QMediaRecorder.Error, errorString:str) # 出现错误时发射信号
mediaFormatChanged() # 格式发生改变时发射信号
metaDataChanged() # 元数据发生改变时发射信号
recorderStateChanged(state:QMediaRecorder.RecorderState) # 录制状态发生改变时发射信号
用 recorderState() 方法 获取录制状态,返回值是 QMediaRecorder.RecorderState 类型的枚举值,可能的取值如下:
QMediaRecorder.RecorderState.StoppedState
QMediaRecorder.RecorderState.RecordingState
QMediaRecorder.RecorderState.PausedState
录制过程中如果出错,可以用 error() 方法 获取出错内容,返回值是 QMediaRecorder.Error 类型的枚举值,可以取值如下:
QMediaRecorder.Error.NoError # 没有问题
QMediaRecorder.Error.ResourceError # 设备没有准备好
QMediaRecorder.Error.FormatError # 不支持该格式
QMediaRecorder.Error.OutOfSpaceError # 存储空间不足
QMediaRecorder.Error.LocationNotWritable # 输出位置不可写
用 setEncodingMode(mode:QMediaRecorder.EncodingMode) 方法 设置编码模式,参数 mode 是 QMediaRecorder.EncodingMode 类型的枚举值,可以取值如下:
QMediaRecorder.EncodingMode.ConstantQualityEncoding # 常质量编码
QMediaRecorder.EncodingMode.ConstantBitRateEncoding # 常比特率编码
QMediaRecorder.EncodingMode.AverageBitRateEncoding # 平均比特率编码
QMediaRecorder.EncodingMode.TwoPassEncoding # 二次编码
用 setQuality(quality:QMediaRecorder.Quality) 方法 设置录制质量,参数 quality 是 QMediaRecorder.Quality 类型的枚举值,可以取如下:
QMediaRecorder.Quality.VeryLowQuality
QMediaRecorder.Quality.LowQuality
QMediaRecorder.Quality.NormalQuality
QMediaRecorder.Quality.HighQuality
QMediaRecorder.Quality.VeryHighQuality
修改 ui.py 文件的内容。
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QToolBar
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtGui import Qt, QIcon
from PySide6.QtMultimediaWidgets import QVideoWidget
class MyUi:
def setupUi(self, window:QWidget):
window.resize(800, 600) # 1.设置窗口对象大小
layout = QVBoxLayout(window) # 2.创建一个垂直布局
self.toolBar = QToolBar() # 3.创建一个工具栏,并添加到布局中
layout.addWidget(self.toolBar)
self.toolBar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon) # 4.设置工具栏的显示样式
# 5.往工具栏中添加动作
self.camera_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "打开摄像头")
self.camera_recorder_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "开始录像")
self.camera_stop_recorder_action = self.toolBar.addAction(QIcon("assets/images/1.ico"), "停止录像")
self.videoWidget = QVideoWidget() # 6.创建显示视频的控件,并添加到布局中
layout.addWidget(self.videoWidget)
修改 widget.py 文件的内容。
import sys
import os
import time
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QUrl
from PySide6.QtMultimedia import QMediaDevices, QCamera
from PySide6.QtMultimedia import QMediaCaptureSession, QMediaRecorder, QMediaFormat
from PySide6.QtMultimedia import QAudioInput, QMediaFormat
from ui import MyUi
class MyWidget(QWidget):
def __init__(self):
super().__init__() # 1.调用父类Qwidget类的__init__()方法
self.__ui = MyUi()
self.__ui.setupUi(self) # 2.初始化页面
self.mediaDevice = QMediaDevices(self) # 3.创建媒体设备
self.cameraDevice = self.mediaDevice.defaultVideoInput() # 4.获取默认的视频输入设备
self.camera = QCamera(self.cameraDevice) # 5.根据视频输入设备定义视频接口
self.mediaCaptureSession = QMediaCaptureSession(self) # 6.创建媒体捕获器
self.mediaCaptureSession.setCamera(self.camera) # 7.设置设备媒体捕获器的视频接口
self.mediaCaptureSession.setVideoOutput(self.__ui.videoWidget) # 8.设置媒体捕获器的视频输出控件
# 9.动作被触发时发送信号
self.__ui.camera_action.triggered.connect(self.camera_action)
self.__ui.camera_recorder_action.triggered.connect(self.camera_recorder_action)
self.__ui.camera_stop_recorder_action.triggered.connect(self.camera_stop_recorder)
def camera_action(self):
if self.__ui.camera_action.text() == "打开摄像头":
self.camera.start() # 1.打开摄像头
self.__ui.camera_action.setText("关闭摄像头") # 2.摄像头操作按钮文本显示为关闭摄像头
self.mediaRecorder = QMediaRecorder(self.camera) # 3.创建媒体录制对象,并关联摄像头
self.mediaRecorder.setMediaFormat(QMediaFormat.FileFormat.MPEG4) # 4.设置视频编码格式
self.mediaRecorder.setVideoResolution(1920, 1080) # 5.设置分辨率
self.mediaRecorder.setQuality(QMediaRecorder.Quality.HighQuality) # 6.设置输出视频的质量
file_name = f"{os.getcwd()}/{time.strftime('%Y%m%d%H%M%S', time.localtime())}.mp4"
self.mediaRecorder.setOutputLocation(QUrl.fromLocalFile(file_name)) # 7.设置媒体输出位置
self.audioInput = QAudioInput() # 8.创建音频输出
self.mediaCaptureSession.setAudioInput(self.audioInput) # 9.设置音频输出
self.mediaCaptureSession.setRecorder(self.mediaRecorder) # 10.设置捕获器
self.mediaRecorder.errorOccurred.connect(self.error)
elif self.__ui.camera_action.text() == "关闭摄像头":
self.camera.stop() # 11.关闭摄像头
self.__ui.camera_action.setText("打开摄像头") # 12.摄像头操作按钮文本显示为打开摄像头
self.imageCapture = None # 13.图片捕获对象设置为空
def camera_recorder_action(self):
if self.mediaRecorder:
if self.__ui.camera_recorder_action.text() == "开始录像":
self.mediaRecorder.record() # 1.录制视频
self.__ui.camera_recorder_action.setText("暂停录像") # 2.录制操作按钮文本显示为暂停录像
elif self.__ui.camera_recorder_action.text() == "暂停录像":
self.mediaRecorder.pause() # 3.暂停录像
self.__ui.camera_recorder_action.setText("开始录像") # 4.录制操作按钮文本显示为开始录像
def camera_stop_recorder(self):
if self.mediaRecorder:
self.mediaRecorder.stop() # 1.结束录像
self.__ui.camera_recorder_action.setText("开始录像") # 2.录制操作按钮文本显示为开始录像
self.camera.stop() # 3.关闭摄像头
self.__ui.camera_action.setText("打开摄像头") # 4.摄像头操作按钮文本显示为打开摄像头
self.mediaRecorder = None # 5.设置捕获器为空
def error(self, error, errorString):
print(error)
print(errorString)
if __name__ == "__main__":
app = QApplication(sys.argv) # 1.创建一个QApplication类的实例
window = MyWidget() # 2.创建一个窗口
window.show() # 3.展示窗口
sys.exit(app.exec()) # 4.进入程序的主循环并通过exit()函数确保主循环安全结束

浙公网安备 33010602011771号