Architektur der CameraX-Videoaufnahme

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">
</ph> Konzeptionelles Diagramm für ein Video- und Audioaufnahmesystem
Abbildung 1: Konzeptionelles Diagramm für ein Video und Audio Aufnahmesystem erfasst.

In CameraX besteht die Lösung für Videoaufnahmen VideoCapture Anwendungsfall:

<ph type="x-smartling-placeholder">
</ph> Konzeptionelles Diagramm, das zeigt, wie Kamera x
         Anwendungsfall für Videoaufnahmen
Abbildung 2: Konzeptionelles Diagramm, das zeigt, wie CameraX kümmert sich um den Anwendungsfall VideoCapture.

Wie in Abbildung 2 gezeigt, umfasst die CameraX-Videoaufzeichnung einige Architekturkomponenten:

  • SurfaceProvider für die Videoquelle.
  • AudioSource fü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:

  • VideoCapture ist der/die/das Top-Level-Anwendungsfallklasse. VideoCapture bindet an ein LifecycleOwner mit einem CameraSelector und einem anderen CameraX Anwendungsfälle. Weitere Informationen zu diesen Konzepten und Verwendungen finden Sie unter CameraX-Architektur
  • Ein Recorder ist ein Implementierung von VideoOutput, das eng mit VideoCapture gekoppelt ist. Recorder wird für die Video- und Audioaufnahme verwendet. Eine App erstellt Aufnahmen aus einem Recorder.
  • PendingRecording konfiguriert eine Aufnahme und bietet Optionen wie das Aktivieren der Audiofunktion und Event-Listener. Sie müssen einen Recorder verwenden, um einen PendingRecording zu erstellen. Mit PendingRecording wird nichts aufgezeichnet.
  • Ein Recording führt die der eigentlichen Aufnahme. Sie müssen einen PendingRecording verwenden, um einen Recording zu erstellen.

Abbildung 3 zeigt die Beziehungen zwischen diesen Objekten:

<ph type="x-smartling-placeholder">
</ph> Diagramm, das die Interaktionen in einem Video zeigt
         Anwendungsfall erfassen
Abbildung 3: Diagramm mit den auftretenden Interaktionen VideoCapture-Anwendungsfall.

Legende:

  1. Recorder erstellen mit QualitySelector
  2. Konfigurieren Sie die Recorder mit einer der OutputOptions
  3. Audio aktivieren mit withAudioEnabled() wenn nötig.
  4. start() anrufen mit VideoRecordEvent Listener, um die Aufzeichnung zu starten.
  5. pause()/resume()/stop() verwenden für Recording um die Aufzeichnung zu steuern.
  6. VideoRecordEvents antworten 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:

  1. Bindung VideoCapture.
  2. Aufzeichnung vorbereiten und konfigurieren
  3. 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:

  1. Erstellen Sie ein Recorder-Objekt.
  2. Erstellen Sie ein VideoCapture-Objekt.
  3. An Lifecycle binden.

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.UHD für 4K-Ultra-HD-Videogröße (2160p)
  • Quality.FHD für Full-HD-Videogröße (1080p)
  • Quality.HD für HD-Videogröße (720p)
  • Quality.SD fü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 specification von QualitySelector. . 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 den VideoCapture-Anwendungsfall oder den Kombination aus VideoCapture- und Preview-Anwendungsfällen. Bei Bindung mit Anwendungsfall: ImageCapture oder ImageAnalysis, 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:

  1. Konfigurieren Sie OutputOptions mit der prepareRecording().
  2. Optional: Aktivieren Sie die Audioaufnahme.
  3. Mit start() registrieren: VideoRecordEvent und 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:

  • FileDescriptorOutputOptions zum Erfassen in ein FileDescriptor
  • FileOutputOptions zum Erfassen in File.
  • MediaStoreOutputOptions zum Erfassen in ein MediaStore

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));
}
  VideoCaptureR<ecorder >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:

  • pause um 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_STATUS wird für die Aufzeichnung von Statistiken wie aktuelle Dateigröße und aufgezeichneter Zeitraum.
  • VideoRecordEvent.EVENT_TYPE_FINALIZE wird 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: