Ein Aufnahmesystem zeichnet in der Regel Video- und Audiostreams auf, komprimiert sie muxt die beiden Streams und schreibt den resultierenden Stream dann auf die Festplatte.
<ph type="x-smartling-placeholder">
In CameraX besteht die Lösung für Videoaufnahmen
VideoCapture
Anwendungsfall:
VideoCapture.Wie in Abbildung 2 gezeigt, umfasst die CameraX-Videoaufzeichnung einige Architekturkomponenten:
SurfaceProviderfür die Videoquelle.AudioSourcefür Audioquelle.- Zwei Encoder zum Codieren und Komprimieren von Video/Audio.
- Einen Media-Muxer zum Muxen der beiden Streams
- Ein Dateispeicher zum Ausschreiben des Ergebnisses.
Die VideoCapture API abstrahiert die komplexe Erfassungs-Engine und bietet mit einer wesentlich einfacheren und unkomplizierteren API erstellen.
VideoCapture API
VideoCapture ist ein Anwendungsfall von CameraX, der allein oder in der Praxis gut funktioniert
in Kombination mit anderen Anwendungsfällen. Speziell unterstützte Kombinationen hängen vom
der Kamera-Hardware, aber Preview und VideoCapture sind
für alle Geräte eine gültige Anwendungsfallkombination.
Die VideoCapture API besteht aus den folgenden Objekten, die miteinander kommunizieren. mit Anwendungen:
VideoCaptureist der/die/das Top-Level-Anwendungsfallklasse.VideoCapturebindet an einLifecycleOwnermit einemCameraSelectorund einem anderen CameraX Anwendungsfälle. Weitere Informationen zu diesen Konzepten und Verwendungen finden Sie unter CameraX-Architektur- Ein
Recorderist ein Implementierung von VideoOutput, das eng mitVideoCapturegekoppelt ist.Recorderwird für die Video- und Audioaufnahme verwendet. Eine App erstellt Aufnahmen aus einemRecorder. PendingRecordingkonfiguriert eine Aufnahme und bietet Optionen wie das Aktivieren der Audiofunktion und Event-Listener. Sie müssen einenRecorderverwenden, um einenPendingRecordingzu erstellen. MitPendingRecordingwird nichts aufgezeichnet.- Ein
Recordingführt die der eigentlichen Aufnahme. Sie müssen einenPendingRecordingverwenden, um einenRecordingzu erstellen.
Abbildung 3 zeigt die Beziehungen zwischen diesen Objekten:
<ph type="x-smartling-placeholder">
Legende:
Recordererstellen mitQualitySelector- Konfigurieren Sie die
Recordermit einer derOutputOptions - Audio aktivieren mit
withAudioEnabled()wenn nötig. start()anrufen mitVideoRecordEventListener, um die Aufzeichnung zu starten.pause()/resume()/stop()verwenden fürRecordingum die Aufzeichnung zu steuern.VideoRecordEventsantworten in Ihrem Event-Listener auf.
Eine detaillierte API-Liste finden Sie in der current.txt-Datei im Quellcode.
VideoCapture API verwenden
So integrierst du den VideoCapture-Anwendungsfall von CameraX in deine App:
Gehen Sie so vor:
- Bindung
VideoCapture. - Aufzeichnung vorbereiten und konfigurieren
- Laufzeitaufzeichnung starten und steuern.
In den folgenden Abschnitten wird beschrieben, was Sie in den einzelnen Schritten tun können, um eine Ende-zu-Ende-Aufzeichnung.
VideoCapture binden
So binden Sie den Anwendungsfall VideoCapure:
- Erstellen Sie ein
Recorder-Objekt. - Erstellen Sie ein
VideoCapture-Objekt. - An
Lifecyclebinden.
Die CameraX VideoCapture API folgt dem Designmuster des Builders. Anwendungen
Verwenden Sie Recorder.Builder, um ein Recorder zu erstellen. Sie können auch die
Videoauflösung für das Recorder über ein QualitySelector-Objekt.
CameraX-Recorder unterstützt die folgenden vordefinierten Qualities
für Videoauflösungen:
Quality.UHDfür 4K-Ultra-HD-Videogröße (2160p)Quality.FHDfür Full-HD-Videogröße (1080p)Quality.HDfür HD-Videogröße (720p)Quality.SDfür SD-Videogröße (480p)
Beachte, dass KameraX auch andere Auflösungen auswählen kann, wenn dies von der App autorisiert wird.
Die genaue Videogröße jeder Auswahl hängt von der
Funktionen. Weitere Informationen finden Sie in der Dokumentation zu
CamcorderProfile
Anwendungen können die Auflösung konfigurieren, indem ein
QualitySelector
Sie können ein QualitySelector-Objekt mit einer der folgenden Methoden erstellen:
Geben Sie einige bevorzugte Lösungen an, indem Sie
fromOrderedList()verwenden und eine Fallback-Strategie für den Fall, dass keine der Auflösungen unterstützt.Die beste Fallback-Lösung kann von CameraX anhand der Weitere Informationen finden Sie in der
FallbackStrategy specificationvonQualitySelector. . Mit dem folgenden Code wird beispielsweise die höchste unterstützte Auflösung für die Aufzeichnung. Falls keine der Auflösungen der Anfrage unterstützt wird, autorisiere CameraX, die Option auszuwählen, die der SD-Auflösung am nächsten kommt:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))Fragen Sie zuerst die Kamerafunktionen ab und wählen Sie dann eine der unterstützten Funktionen aus. Auflösungen mit
QualitySelector::from():val cameraInfo = cameraProvider.availableCameraInfos.filter { Camera2CameraInfo .from(it) .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK } val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0]) val filteredQualities = arrayListOf (Quality.UHD, Quality.FHD, Quality.HD, Quality.SD) .filter { supportedQualities.contains(it) } // Use a simple ListView with the id of simple_quality_list_view viewBinding.simpleQualityListView.apply { adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredQualities.map { it.qualityToString() }) // Set up the user interaction to manually show or hide the system UI. setOnItemClickListener { _, _, position, _ -> // Inside View.OnClickListener, // convert Quality.* constant to QualitySelector val qualitySelector = QualitySelector.from(filteredQualities[position]) // Create a new Recorder/VideoCapture for the new quality // and bind to lifecycle val recorder = Recorder.Builder() .setQualitySelector(qualitySelector).build() // ... } } // A helper function to translate Quality to a string fun Quality.qualityToString() : String { return when (this) { Quality.UHD -> "UHD" Quality.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }Beachten Sie, dass die von
QualitySelector.getSupportedQualities()ist garantiert entweder für denVideoCapture-Anwendungsfall oder den Kombination ausVideoCapture- undPreview-Anwendungsfällen. Bei Bindung mit Anwendungsfall:ImageCaptureoderImageAnalysis, CameraX kann die Bindung dennoch fehlschlagen, wenn die erforderliche Kombination auf die angeforderte Kamera.
Sobald Sie eine QualitySelector haben, kann die Anwendung ein
VideoCapture-Objekt und führen Sie die Bindung aus. Diese Bindung ist
wie bei anderen Anwendungsfällen:
val recorder = Recorder.Builder()
.setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
.build()
val videoCapture = VideoCapture.withOutput(recorder)
try {
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
bindToLifecycle() gibt ein Camera-Objekt zurück. In dieser Anleitung findest du weitere Informationen zur Steuerung der Kameraausgabe, wie z. B. Zoom und Belichtung.
Mit Recorder wird das am besten geeignete Format für das System ausgewählt. Die meisten
gängiger Video-Codec ist
H.264 AVC) mit
Containerformat
MPEG-4:
Aufzeichnung konfigurieren und erstellen
Aus einem Recorder kann die App Aufnahmeobjekte erstellen,
die Video- und Audioaufnahme durchzuführen. Anwendungen erstellen Aufzeichnungen
Folgendes:
- Konfigurieren Sie
OutputOptionsmit derprepareRecording(). - Optional: Aktivieren Sie die Audioaufnahme.
- Mit
start()registrieren:VideoRecordEventund beginnen mit der Videoaufnahme.
Recorder gibt ein Recording-Objekt zurück, wenn du die start()-Funktion aufrufst.
Ihre Anwendung kann dieses Recording-Objekt verwenden, um die
oder bestimmte Aktionen wie das Pausieren oder Fortsetzen
ausführen.
Eine Recorder unterstützt jeweils nur ein Recording-Objekt. Sie können eine
eine neue Aufnahme, nachdem du Recording.stop() angerufen hast, oder
Recording.close() für das vorherige Recording-Objekt.
Sehen wir uns diese Schritte etwas genauer an. Zunächst konfiguriert die Anwendung
OutputOptions für einen Rekorder mit Recorder.prepareRecording().
Ein Recorder unterstützt die folgenden OutputOptions-Typen:
FileDescriptorOutputOptionszum Erfassen in einFileDescriptorFileOutputOptionszum Erfassen inFile.MediaStoreOutputOptionszum Erfassen in einMediaStore
Bei allen OutputOptions-Typen können Sie mit
setFileSizeLimit(). Andere Optionen sind spezifisch für die jeweilige Ausgabe
-Typ, z. B. ParcelFileDescriptor für die FileDescriptorOutputOptions.
prepareRecording() gibt ein PendingRecording-Objekt zurück, bei dem es sich um
Zwischenobjekt, mit dem das entsprechende
Recording-Objekt. PendingRecording ist eine temporäre Klasse, die
in den meisten Fällen unsichtbar und wird selten von der App im Cache gespeichert.
Anwendungen können die Aufzeichnung weiter konfigurieren, z. B.:
- Aktivieren Sie Audio mit
withAudioEnabled(). - Listener für den Empfang von Videoaufnahmeereignissen registrieren
mit
start(Executor, Consumer<VideoRecordEvent>). - Ununterbrochene Aufnahme einer Aufzeichnung erlauben, während VideoCapture an das Video angehängt ist
an eine andere Kamera gebunden.
PendingRecording.asPersistentRecording()
Wenn du die Aufzeichnung starten möchtest, ruf PendingRecording.start() an. CameraX dreht die
PendingRecording in eine Recording ein, stellt die Aufnahmeanfrage in die Warteschlange,
und gibt das neu erstellte Recording-Objekt an die Anwendung zurück.
Sobald die Aufnahme auf der entsprechenden Kamera beginnt, sendet CameraX eine
VideoRecordEvent.EVENT_TYPE_START-Ereignis.
Das folgende Beispiel zeigt, wie Sie Video- und Audioinhalte in eine
MediaStore-Datei:
// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
.setContentValues(contentValues)
.build()
// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
.prepareRecording(context, mediaStoreOutput)
.withAudioEnabled()
.start(ContextCompat.getMainExecutor(this), captureListener)
Während die Kameravorschau auf der Frontkamera standardmäßig gespiegelt wird, werden in Videos aufgenommene Videos werden standardmäßig nicht gespiegelt. Mit CameraX 1.3 Videoaufnahmen können jetzt gespiegelt werden, sodass die Frontkamera-Vorschau und Videoaufnahme übereinstimmen.
Es gibt drei MirrorMode-Optionen: MIRROR_MODE_OFF, MIRROR_MODE_ON und
MIRROR_MODE_ON_FRONT_ONLY Um sie am
die Kameravorschau zeigt, empfiehlt Google die Verwendung von MIROR_MODE_ON_FRONT_ONLY. Das bedeutet,
das
Die Spiegelung ist für die Rückkamera nicht aktiviert, für die Frontkamera ist sie aktiviert
Kamera. Weitere Informationen zum Spiegelmodus finden Sie unter
MirrorMode constants
Dieses Code-Snippet zeigt, wie ein
VideoCapture.Builder.setMirrorMode() mit MIRROR_MODE_ON_FRONT_ONLY. Für
Weitere Informationen finden Sie unter setMirrorMode().
Kotlin
val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build() useCases.add(videoCapture);
Java
Recorder.Builder builder = new Recorder.Builder(); if (mVideoQuality != QUALITY_AUTO) { builder.setQualitySelector( QualitySelector.from(mVideoQuality)); } VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(builder.build()) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build(); useCases.add(videoCapture);
Aktive Aufzeichnung steuern
Sie können eine laufende Recording pausieren, fortsetzen und beenden,
mithilfe der folgenden Methoden:
pauseum die aktuell aktive Aufzeichnung anzuhalten.resume()um eine pausierte aktive Aufzeichnung fortzusetzen.stop()um die Aufzeichnung abzuschließen und alle zugehörigen Aufnahmeobjekte zu leeren.mute()um die aktuelle Aufnahme stummzuschalten bzw. die Stummschaltung aufzuheben.
Beachten Sie, dass Sie unabhängig davon stop() aufrufen können, um eine Recording zu beenden.
ob die Aufzeichnung pausiert oder aktiv ist.
Wenn du eine EventListener registriert hast mit
PendingRecording.start(), die Recording kommuniziert
mit einer
VideoRecordEvent
VideoRecordEvent.EVENT_TYPE_STATUSwird für die Aufzeichnung von Statistiken wie aktuelle Dateigröße und aufgezeichneter Zeitraum.VideoRecordEvent.EVENT_TYPE_FINALIZEwird für das Aufnahmeergebnis verwendet und Informationen wie den URI der endgültigen Datei sowie eventuellen Fehlern.
Sobald deine App eine EVENT_TYPE_FINALIZE erhält, die eine erfolgreiche
Aufzeichnungssitzung können Sie dann vom Standort aus auf das aufgenommene Video zugreifen.
in OutputOptions angegeben.
Weitere Informationen
Weitere Informationen zu CameraX finden Sie in den folgenden zusätzlichen Ressourcen:
- Codelab: Erste Schritte mit CameraX
- Offizielle CameraX-Beispiel-App
- Liste der neuesten CameraX Video Capture API
- Versionshinweise zu CameraX
- CameraX-Quellcode