使用 Qt Quick 录制音频和视频。
QML Recorder demonstrates a simple application that can record audio and video separate or together, using a microphone, a camera, or with screen capturing.
要运行范例从 Qt Creator ,打开 Welcome 模式,然后选择范例从 Examples 。更多信息,拜访 构建和运行范例 .
At its core, this is a QML application, see 采用 Qt Quick 快速入门编程 . This documentation is focused on how this example uses the Qt Multimedia QML types .
The example uses the QML Camera and AudioInput types connected to a CaptureSession 。 MediaRecorder object is then used to record the captured audio and video.
除了 QtMultimedia , features of Qt Quick Windows, Controls, and Layouts are used to implement the graphic user interface and functionality. Playback won't be covered here, for that see the QML 媒体播放器范例 .
The example demonstrates the following:
The application implements recording.
在
main.qml
,
captureSession
is declared like so:
CaptureSession {
id: captureSession
recorder: recorder
audioInput: controls.audioInput
camera: controls.camera
screenCapture: controls.screenCapture
videoOutput: videoOutput
}
在
main.qml
,
MediaRecorder
recorder
handles recording media as well as capturing a thumbnail for the file and appending it to a ListModel,
mediaList
.
MediaRecorder {
id: recorder
onRecorderStateChanged:
(state) => {
if (state === MediaRecorder.StoppedState) {
root.contentOrientation = Qt.PrimaryOrientation
mediaList.append()
} else if (state === MediaRecorder.RecordingState && captureSession.camera) {
// lock orientation while recording and create a preview image
root.contentOrientation = root.screen.orientation;
videoOutput.grabToImage(function(res) { mediaList.mediaThumbnail = res.url })
}
}
onActualLocationChanged: (url) => { mediaList.mediaUrl = url }
onErrorOccurred: { recorderErrorText.text = recorder.errorString; recorderError.open(); }
}
mediaList
is declared in the
Frame
mediaListFrame
Frame {
id: mediaListFrame
height: 150
width: parent.width
anchors.bottom: controlsFrame.top
x: controls.capturesVisible ? 0 : parent.width
background: Rectangle {
anchors.fill: parent
color: "white"
opacity: 0.8
}
Behavior on x { NumberAnimation { duration: 200 } }
MediaList {
id: mediaList
anchors.fill: parent
playback: playback
These are defined in
Controls.qml
and declared in main.qml.
Its root is a
Row
包含
Columns
inputControls
,
recordButton
,
optionButtons
, each defined in their own .qml files.
Defined in
VideoSourceSelect.qml
,
VideoSourceSlect
is comprised of a
Switch
和
ComboBox
and enables the user to select from available cameras.
Row { id: root height: Style.height property Camera selectedCamera: cameraAvailable ? camera : null property ScreenCapture selectedScreenCapture: screenAvailable ? screenCapture : null property bool cameraAvailable: (comboBox.currentValue.type === 'camera') && cameraSwitch.checked property bool screenAvailable: (comboBox.currentValue.type === 'screen') && cameraSwitch.checked Component.onCompleted: { videoSourceModel.populate() comboBox.currentIndex = 0 } Camera { id: camera active: cameraAvailable } ScreenCapture { id: screenCapture active: screenAvailable } MediaDevices { id: mediaDevices } Switch { id: cameraSwitch anchors.verticalCenter: parent.verticalCenter checked: true } ListModel { id: videoSourceModel property var cameras: mediaDevices.videoInputs property var screens: Application.screens function populate() { videoSourceModel.clear() for (var camera of cameras) videoSourceModel.append({ text: camera.description, value: { type: 'camera', camera: camera } }) for (var screen of screens) videoSourceModel.append({ text: screen.name, value: { type: 'screen', screen: screen }}) } }
comboBox
, declared in the above snippet, assigns the current video source.
ComboBox {
id: comboBox
width: Style.widthLong
height: Style.height
background: StyleRectangle { anchors.fill: parent }
model: videoSourceModel
displayText: typeof currentValue === 'undefined' ? "Unavailable" : currentText
font.pointSize: Style.fontSize
textRole: "text"
valueRole: "value"
onCurrentValueChanged: {
if (currentValue.type === 'screen')
screenCapture.screen = currentValue.screen
else if (currentValue.type === 'camera')
camera.cameraDevice = currentValue.camera
Implemented in the same way as
Selecting a video source
and defined in
AudioInputSelect.qml
像这样:
Row { id: root height: Style.height property AudioInput selected: available ? audioInput : null property bool available: (typeof comboBox.currentValue !== 'undefined') && audioSwitch.checked Component.onCompleted: { audioInputModel.populate() comboBox.currentIndex = 0 } MediaDevices { id: mediaDevices } AudioInput { id: audioInput; muted: !audioSwitch.checked } Switch { id: audioSwitch; height: Style.height; checked: true } ListModel { id: audioInputModel property var audioInputs: mediaDevices.audioInputs function populate() { audioInputModel.clear() for (var audioInput of audioInputs) audioInputModel.append({ text: audioInput.description, value: { type: 'audioInput', audioInput: audioInput } }) } } ComboBox { id: comboBox width: Style.widthLong height: Style.height background: StyleRectangle { anchors.fill: parent } model: audioInputModel textRole: "text" font.pointSize: Style.fontSize displayText: typeof currentValue === 'undefined' ? "unavailable" : currentText valueRole: "value"