QML ビデオレコーダー
Qt Quick を使って音声と動画を記録します。
QML Recorderでは、マイクやカメラ、あるいはスクリーンキャプチャを使って、音声と動画を別々に、あるいは一緒に記録できるシンプルなアプリケーションをデモします。
サンプルを実行する
Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。
概要
Qt Quick でプログラミングを始める」を参照してください。このドキュメントは、このサンプルがQt Multimedia QML Types をどのように使うかに焦点を当てています。
この例では、CaptureSession に接続された QMLCamera とAudioInput を使用しています。MediaRecorder は、キャプチャされた音声と映像を記録するために使用されます。
QtMultimedia に加えて、Qt Quick Windows、Controls、Layouts の機能が、グラフィッ ク・ユーザー・インターフェイスと機能を実装するために使われています。再生については、QML Media Player Exampleを参照してください。
この例では、以下のようなことを実現しています:
- 入力デバイスの選択
- 入力タイプのスイッチオフ。
- 品質、コーデックの選択、ファイル形式、メタデータの割り当てなど、キャプチャのための設定。
- キャプチャされたファイルは保存され、再生することができます。
録画
アプリケーションは録画を実装しています。
キャプチャセッション
main.qml
では、captureSession
のように宣言されています:
CaptureSession { id: captureSession recorder: recorder audioInput: controls.audioInput camera: controls.camera screenCapture: controls.screenCapture windowCapture: controls.windowCapture videoOutput: videoOutput }
レコーダー
main.qml
では、MediaRecorder recorder
、メディアの記録と、ファイルのサムネイルをキャプチャして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
は で宣言されている。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: palette.base opacity: 0.8 } Behavior on x { NumberAnimation { duration: 200 } } MediaList { id: mediaList anchors.fill: parent playback: playback
コントロール
これらはControls.qml
で定義され、main.qmlで宣言されている。
そのルートはColumns inputControls
recordButton
optionButtons
を含むRow であり、それぞれ独自の .qml ファイルで定義されています。
ビデオソースの選択
VideoSourceSelect.qml
で定義されているVideoSourceSlect
は、Switch とComboBox で構成され、利用可能なカメラから選択することができます。
Row { id: root height: Style.height property Camera selectedCamera: cameraAvailable ? camera : null property ScreenCapture selectedScreenCapture: screenAvailable ? screenCapture : null property WindowCapture selectedWindowCapture: windowAvailable ? windowCapture : null property bool sourceAvailable: typeof comboBox.currentValue !== 'undefined' && comboBox.currentValue.type !== 'toggler' && videoSourceSwitch.checked property bool cameraAvailable: sourceAvailable && comboBox.currentValue.type === 'camera' property bool screenAvailable: sourceAvailable && comboBox.currentValue.type === 'screen' property bool windowAvailable: sourceAvailable && comboBox.currentValue.type === 'window' Component.onCompleted: { videoSourceModel.populate() for (var i = 0; i < videoSourceModel.count; i++) { if (videoSourceModel.get(i).value.type !== 'toggler') { comboBox.currentIndex = i break } } } Camera { id: camera active: cameraAvailable } ScreenCapture { id: screenCapture active: screenAvailable } WindowCapture { id: windowCapture active: windowAvailable } MediaDevices { id: mediaDevices onVideoInputsChanged: { videoSourceModel.populate() for (var i = 0; i < videoSourceModel.count; i++) { if (videoSourceModel.get(i).value.type !== 'toggler') { comboBox.currentIndex = i break } } } } Switch { id: videoSourceSwitch anchors.verticalCenter: parent.verticalCenter checked: true } ListModel { id: videoSourceModel property var enabledSources: { 'camera': true, 'screen': true, 'window': false } function toggleEnabledSource(type) { enabledSources[type] = !enabledSources[type] populate() } function appendItem(text, value) { append({ text: text, value: value}) } function appendToggler(name, sourceType) { appendItem((enabledSources[sourceType] ? "- Hide " : "+ Show ") + name, { type: 'toggler', 'sourceType': sourceType }) } function populate() { clear() appendToggler('Cameras', 'camera') if (enabledSources['camera']) for (var camera of mediaDevices.videoInputs) appendItem(camera.description, { type: 'camera', camera: camera }) appendToggler('Screens', 'screen') if (enabledSources['screen']) for (var screen of Application.screens) appendItem(screen.name, { type: 'screen', screen: screen }) appendToggler('Windows', 'window') if (enabledSources['window']) for (var window of windowCapture.capturableWindows()) appendItem(window.description, { type: 'window', window: window }) } }
comboBox
上記のスニペットで宣言された「ビデオ・ソース」は、現在のビデオ・ソースを割り当てます。
ComboBox { id: comboBox width: Style.widthLong height: Style.height background: StyleRectangle { anchors.fill: parent } model: videoSourceModel displayText: typeof currentValue === 'undefined' || currentValue.type === 'toggler' ? "Unavailable" : currentText font.pointSize: Style.fontSize textRole: "text" valueRole: "value" onCurrentValueChanged: { if (typeof currentValue === 'undefined') return if (currentValue.type === 'screen') screenCapture.screen = currentValue.screen else if (currentValue.type === 'camera') camera.cameraDevice = currentValue.camera
オーディオ入力の選択
ビデオ・ソースの選択と同じように実装され、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 audioDevice of audioInputs) audioInputModel.append({ text: audioDevice.description, value: { type: 'audioDevice', audioDevice: audioDevice } }) } } 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"
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。