使用 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"