Anleitungen

High-Speed-Aufnahmen und Zeitlupenvideos mit CameraX 1.5

Lesezeit: 6 Minuten
Leo Huang
Softwaretechniker

Die Aufnahme von schnellen Bewegungen mit Klarheit ist eine wichtige Funktion für moderne Kamera-Apps. Dies 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 Ausgabevideo flüssig ist, sollte es in der Regel mit mindestens 30 fps gerendert werden. Das bedeutet, dass die ursprüngliche Aufnahmeframerate mindestens 120 fps betragen muss, um ein 4-faches Zeitlupenvideo zu erstellen (120 fps ÷ 4 = 30 fps).

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 Standardframerate (z.B. 30 fps) neu codiert. Der Zeitlupeneffekt wird durch Anpassen der Zeitstempel der Bilder „eingebaut“. Das resultierende Video wird in jedem Standardvideoplayer ohne besondere Behandlung 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 dies, 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 Datei build.gradle.kts 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 befinden sich derzeit in der Testphase. Das bedeutet, dass sie sich in zukünftigen Versionen ändern können. Wenn Sie sie verwenden möchten, müssen Sie sie aktivieren, 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 Entscheidung 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 Einrichtungsprozess in einer suspend-Funktion. Sie können diese Funktion über einen 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 ein Video in jedem Standardvideoplayer automatisch in Zeitlupe wiedergegeben werden soll.

  // 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 Standardvideodatei mit 30 fps. Die Zeitlupengeschwindigkeit wird durch das Verhältnis der Aufnahmeframerate zu dieser Standardwiedergaberate 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).

Zusammenfassung: Video aufnehmen

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

In diesem Beitrag geht es 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 zur Verarbeitung der VideoRecordEvent-Callbacks finden Sie in der Dokumentation zu VideoCapture.

  // 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 Standardvideoplayern und Galerie-Apps sofort als Zeitlupe erkannt und wiedergegeben werden kann. Google Fotos bietet insbesondere erweiterte Funktionen für diese Zeitlupenvideos, wenn die Aufnahmeframerate 120, 240, 360, 480 oder 960 fps beträgt:

  • Eindeutige UI-Erkennung im Thumbnail: In Ihrer Google Fotos-Mediathek können Zeitlupenvideos anhand bestimmter UI-Elemente erkannt werden, die sie von normalen Videos unterscheiden.
normal.png
  • Anpassbare Geschwindigkeitssegmente während der Wiedergabe: Bei der Wiedergabe eines Zeitlupenvideos 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

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 gemeldeten 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 ist die Unterstützung garantiert, da diese High-Speed-Profile immer enthalten. 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 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 Flags setSlowMotionEnabled verstehen, können Sie beide Anwendungsfälle problemlos unterstützen und Ihren Nutzern mehr kreative Kontrolle geben.

Verfasst von:

Weiterlesen