Anleitungen

High-Speed-Aufnahmen und Zeitlupenvideos mit CameraX 1.5

6 Minuten Lesezeit
Profil von Charles Munger ansehen
Leo Huang Software Engineer

Schnelle Bewegungen klar aufzunehmen, ist eine wichtige Funktion moderner Kamera-Apps. Das wird durch High-Speed-Aufnahmen erreicht, bei denen Bilder mit einer Geschwindigkeit von 120 oder 240 fps aufgenommen werden. Diese Aufnahmen mit hoher Qualität können für zwei verschiedene Zwecke verwendet werden: zum Erstellen eines Videos mit hoher Framerate für eine detaillierte, bildweise Analyse oder zum Erstellen eines Zeitlupenvideos, in dem die Action auf dem Bildschirm dramatisch dargestellt wird.

Bisher war die Implementierung dieser Funktionen mit der Camera2 API aufwendiger. Mit der neuen High-Speed-API in CameraX 1.5 wird der gesamte Prozess vereinfacht. Sie haben die Flexibilität, entweder echte Videos mit hoher Framerate oder abspielbereite Zeitlupenvideos zu erstellen. In diesem Beitrag erfahren Sie, wie Sie beides bewerkstelligen. Wenn Sie CameraX noch nicht kennen, können Sie sich in der CameraX-Übersicht informieren.


Das Prinzip hinter Zeitlupe

Das grundlegende Prinzip der Zeitlupe besteht darin, Videos mit einer viel höheren Framerate aufzunehmen, als sie wiedergegeben werden. Wenn Sie beispielsweise ein Ereignis von einer Sekunde mit 120 Bildern pro Sekunde (fps) aufnehmen und die Aufnahme dann mit 30 fps wiedergeben, dauert die Wiedergabe vier Sekunden. Durch diese „Dehnung“ der Zeit entsteht der dramatische Zeitlupeneffekt, mit dem Sie Details sehen können, die für das bloße Auge zu schnell sind.

Damit das endgültige Video flüssig ist, sollte es in der Regel mit mindestens 30 fps gerendert werden. Das bedeutet, dass die ursprüngliche Framerate für die Aufnahme mindestens 120 fps betragen muss, um ein 4-faches Zeitlupenvideo zu erstellen (120 fps Aufnahme ÷ 4 = 30 fps Wiedergabe).

Sobald das Filmmaterial mit hoher Framerate aufgenommen wurde, gibt es zwei Hauptmöglichkeiten, das gewünschte Ergebnis zu erzielen:

  • Zeitlupe durch den Player (Video mit hoher Framerate): Die High-Speed-Aufnahme (z.B. 120 fps) wird direkt als Videodatei mit hoher Framerate gespeichert. Dann ist es Aufgabe des Videoplayers, die Wiedergabegeschwindigkeit zu verlangsamen. So kann der Nutzer zwischen normaler und Zeitlupenwiedergabe wechseln.
  • Abspielbereite Zeitlupe (neu codiertes Video): Der High-Speed-Videostream wird verarbeitet und in eine Datei mit einer Standard-Framerate (z.B. 30 fps) neu codiert. Der Zeitlupeneffekt wird durch Anpassen der Zeitstempel der Bilder „eingebaut“. Das resultierende Video wird in jedem Standard-Videoplayer ohne besondere Verarbeitung in Zeitlupe wiedergegeben. Obwohl das Video standardmäßig in Zeitlupe wiedergegeben wird, können Videoplayer Steuerelemente für die Wiedergabegeschwindigkeit bieten, mit denen der Nutzer die Geschwindigkeit erhöhen und das Video mit der ursprünglichen Geschwindigkeit ansehen kann.

Die CameraX API vereinfacht diesen Vorgang, indem sie Ihnen eine einheitliche Möglichkeit bietet, den gewünschten Ansatz auszuwählen, wie Sie unten sehen.


Die neue High-Speed-Video-API

Die neue CameraX-Lösung basiert auf zwei Hauptkomponenten:

  • Recorder#getHighSpeedVideoCapabilities(CameraInfo): Mit dieser Methode können Sie prüfen, ob die Kamera High-Speed-Aufnahmen unterstützt und wenn ja, welche Auflösungen (Quality-Objekte) unterstützt werden.
  • HighSpeedVideoSessionConfig: Dies ist ein spezielles Konfigurationsobjekt, das Ihre VideoCapture und Preview Anwendungsfälle gruppiert und CameraX anweist, eine einheitliche High-Speed-Kamerasitzung zu erstellen. Während der VideoCapture-Stream mit der konfigurierten hohen Framerate ausgeführt wird, wird der Preview-Stream in der Regel vom Kamerasystem auf eine Standardrate von mindestens 30 fps begrenzt, um eine reibungslose Anzeige auf dem Bildschirm zu gewährleisten.

Erste Schritte

Bevor Sie beginnen, müssen Sie der build.gradle.kts-Datei Ihrer App die erforderlichen CameraX-Abhängigkeiten hinzufügen. Sie benötigen das camera-video-Artefakt zusammen mit den CameraX-Kernbibliotheken.

// build.gradle.kts (Module: app)

dependencies {

    val camerax_version = "1.5.1"


    implementation("androidx.camera:camera-core:$camerax_version")

    implementation("androidx.camera:camera-camera2:$camerax_version")

    implementation("androidx.camera:camera-lifecycle:$camerax_version")

    implementation("androidx.camera:camera-video:$camerax_version")

    implementation("androidx.camera:camera-view:$camerax_version")

}

Hinweis zu experimentellen APIs

Die APIs für High-Speed-Aufnahmen sind derzeit experimentell. Das bedeutet, dass sie sich in zukünftigen Versionen ändern können. Wenn Sie sie verwenden möchten, müssen Sie sich anmelden, indem Sie Ihrem Code die folgende Annotation hinzufügen:

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

Implementierung

Die Implementierung für beide Ergebnisse beginnt mit denselben Einrichtungsschritten. Die Wahl zwischen einem Video mit hoher Framerate und einem Zeitlupenvideo hängt von einer einzigen Einstellung ab.

1. High-Speed-Aufnahmen einrichten

Unabhängig von Ihrem Ziel müssen Sie zuerst den ProcessCameraProvider abrufen, die Gerätefunktionen prüfen und Ihre Anwendungsfälle erstellen.

Der folgende Codeblock zeigt den vollständigen Einrichtungsvorgang in einer suspend-Funktion. Sie können diese Funktion aus einem Coroutinenbereich wie lifecycleScope.launch aufrufen.

// Add the OptIn annotation at the top of your function or class

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

private suspend fun setupCamera() {

    // Asynchronously get the CameraProvider

    val cameraProvider = ProcessCameraProvider.awaitInstance(this)



    // -- CHECK CAPABILITIES --

    val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA)

    val videoCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

    if (videoCapabilities == null) {

        // This camera device does not support high-speed video.

        return

    }




    // -- CREATE USE CASES --

    val preview = Preview.Builder().build()    


    // You can create a Recorder with default settings.

    // CameraX will automatically select a suitable quality.

    val recorder = Recorder.Builder().build()


    // Alternatively, to use a specific resolution, you can configure the
    // Recorder with a QualitySelector. This is useful if your app has
    // specific resolution requirements or you want to offer user
    // preferences. 

    // To use a specific quality, you can uncomment the following lines.

    // Get the list of qualities supported for high-speed video. 

    // val supportedQualities = videoCapabilities.getSupportedQualities(DynamicRange.SDR)

    // Build the Recorder using the quality from the supported list.

    // val recorderWithQuality = Recorder.Builder()

    //     .setQualitySelector(QualitySelector.from(supportedQualities.first()))

    //     .build()



    // Create the VideoCapture use case, using either recorder or recorderWithQuality

    val videoCapture = VideoCapture.withOutput(recorder)

    // Now you are ready to configure the session for your desired output...

}

2. Ausgabe auswählen

Jetzt entscheiden Sie, welche Art von Video Sie erstellen möchten. Dieser Code wird in der oben gezeigten setupCamera() suspend-Funktion ausgeführt.

Option A: Video mit hoher Framerate erstellen

Wählen Sie diese Option aus, wenn die endgültige Datei eine hohe Framerate haben soll (z.B. ein Video mit 120 fps).

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)


// Query and apply a supported frame rate. Common supported frame rates include 120 and 240 fps.

val supportedFrameRateRanges =

    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())


sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Option B: Abspielbereites Zeitlupenvideo erstellen

Wählen Sie diese Option aus, wenn Sie ein Video möchten, das in jedem Standard-Videoplayer automatisch in Zeitlupe wiedergegeben wird.

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)



// This is the key: enable automatic slow-motion!

sessionConfigBuilder.setSlowMotionEnabled(true)



// Query and apply a supported frame rate. Common supported frame rates include 120, 240, and 480 fps.

val supportedFrameRateRanges =

   cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())

sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

Dieses einzelne Flag ist der Schlüssel zum Erstellen eines abspielbereiten Zeitlupenvideos. Wenn setSlowMotionEnabled auf „true“ gesetzt ist, verarbeitet CameraX den High-Speed-Stream und speichert ihn als Standard-Videodatei mit 30 fps. Die Zeitlupengeschwindigkeit wird durch das Verhältnis der Framerate der Aufnahme zu dieser Standard-Wiedergaberate bestimmt.

Beispiel:

  • Bei einer Aufnahme mit 120 fps wird ein Video erstellt, das mit 1/4-facher Geschwindigkeit wiedergegeben wird (120 ÷ 30 = 4).
  • Bei einer Aufnahme mit 240 fps wird ein Video erstellt, das mit 1/8-facher Geschwindigkeit wiedergegeben wird (240 ÷ 30 = 8).

Alles zusammenfügen: Video aufnehmen

Sobald Sie HighSpeedVideoSessionConfig konfiguriert und an den Lebenszyklus gebunden haben, müssen Sie nur noch die Aufnahme starten. Der Vorgang zum Vorbereiten der Ausgabeoptionen, Starten der Aufnahme und Verarbeiten von Videoereignissen ist derselbe wie bei einer Standard-Videoaufnahme.

In diesem Beitrag geht es hauptsächlich um die High-Speed-Konfiguration. Daher wird der Aufnahmeprozess nicht im Detail behandelt. Eine umfassende Anleitung zu allen Schritten von der Vorbereitung eines FileOutputOptions oder MediaStoreOutputOptions Objekts bis hin zur Verarbeitung der VideoRecordEvent Callbacks finden Sie in der VideoCapture-Dokumentation.

// Bind the session config to the lifecycle

cameraProvider.bindToLifecycle(

    this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA,

    sessionConfigBuilder.build() // Bind the config object from Option A or B

)



// Start the recording using the VideoCapture use case

val recording = videoCapture.output

    .prepareRecording(context, outputOptions) // See docs for creating outputOptions

    .start(ContextCompat.getMainExecutor(context)) { recordEvent ->

        // Handle recording events (e.g., Start, Pause, Finalize)

    }

Unterstützung für Zeitlupenvideos in Google Fotos

Wenn Sie in CameraX setSlowMotionEnabled(true) aktivieren, ist die resultierende Videodatei so konzipiert, dass sie in Standard-Videoplayern und Galerie-Apps sofort als Zeitlupe erkannt und wiedergegeben werden kann. Google Fotos bietet insbesondere erweiterte Funktionen für diese Zeitlupenvideos, wenn die Framerate der Aufnahme 120, 240, 360, 480 oder 960 fps beträgt:

  • Eindeutige UI-Erkennung im Miniaturbild: In Ihrer Google Fotos-Mediathek können Zeitlupenvideos anhand bestimmter UI-Elemente erkannt werden, die sie von normalen Videos unterscheiden.
normal.png
slowmotion.png
Video-ThumbnailMiniaturbild eines Zeitlupenvideos
  • Anpassbare Geschwindigkeitssegmente während der Wiedergabe: Wenn Sie ein Zeitlupenvideo wiedergeben, bietet Google Fotos Steuerelemente, mit denen Sie anpassen können, welche Teile des Videos in Zeitlupe und welche mit normaler Geschwindigkeit wiedergegeben werden. So haben Nutzer kreative Kontrolle. Das bearbeitete Video kann dann über die Schaltfläche Teilen als neue Videodatei exportiert werden, wobei die von Ihnen definierten Zeitlupensegmente beibehalten werden.
normal2.png
slowmotion2.png
Normale VideowiedergabeZeitlupenvideo 
mit Steuerelementen für die 
Bearbeitung

Hinweis zur Geräteunterstützung

Die High-Speed-API von CameraX verwendet das zugrunde liegende Android CamcorderProfile-System, um zu ermitteln, welche High-Speed-Auflösungen und Frameraten von einem Gerät unterstützt werden. CamcorderProfiles werden von der Android Compatibility Test Suite (CTS) validiert. Sie können sich also auf die angegebenen Videoaufnahmefunktionen des Geräts verlassen.

Das bedeutet, dass die Möglichkeit eines Geräts, mit der integrierten Kamera-App Zeitlupenvideos aufzunehmen, nicht garantiert, dass die High-Speed-API von CameraX funktioniert. Diese Diskrepanz entsteht, weil Gerätehersteller für das Ausfüllen der CamcorderProfile Einträge in der Firmware ihrer Geräte verantwortlich sind. Manchmal sind erforderliche High-Speed-Profile wie CamcorderProfile.QUALITY_HIGH_SPEED_1080P und CamcorderProfile.QUALITY_HIGH_SPEED_720P nicht enthalten. Wenn diese Profile fehlen, gibt Recorder.getHighSpeedVideoCapabilities() null zurück.

Daher ist es wichtig, immer Recorder.getHighSpeedVideoCapabilities() zu verwenden, um programmatisch nach unterstützten Funktionen zu suchen. Dies ist die zuverlässigste Methode, um eine konsistente Nutzererfahrung auf verschiedenen Geräten zu gewährleisten. Wenn Sie versuchen, eine HighSpeedVideoSessionConfig auf einem Gerät zu binden, auf dem Recorder.getHighSpeedVideoCapabilities() „null“ zurückgibt, schlägt der Vorgang mit einer IllegalArgumentException fehl. Auf Google Pixel-Geräten wird die Unterstützung bestätigt, da diese High-Speed-Profile immer enthalten sind. Außerdem unterstützen verschiedene Geräte anderer Hersteller wie das Motorola Edge 30, das OPPO Find N2 Flip und das Sony Xperia 1 V die High-Speed-Videofunktionen.


Fazit

Die High-Speed-Video-API von CameraX ist sowohl leistungsstark als auch flexibel. Ob Sie nun Filmmaterial mit hoher Framerate für technische Analysen benötigen oder Ihrer App filmische Zeitlupeneffekte hinzufügen möchten, HighSpeedVideoSessionConfig bietet eine einheitliche und einfache Lösung. Wenn Sie die Rolle des setSlowMotionEnabled-Flags verstehen, können Sie beide Anwendungsfälle problemlos unterstützen und Ihren Nutzern mehr kreative Kontrolle geben.

Geschrieben von:
Weiterlesen