Recording and Snapshots

A live stream can be recorded to the device’s gallery while it is playing. Recordings are written straight into the Android gallery through MediaStore, so the saved clips appear in the user’s Movies folder and in their photo gallery app.

Pre-requisite: The camera should already be streaming live view before starting a recording.


Start a recording

To start recording the live view, The following method can be used:

  • shouldInterpolate (required): When true, a frame whose pixel count is at or below minMp is upscaled to minWidth × minHeight; otherwise the source resolution is kept. null means false. Ignored on multi-stream cameras, where each sensor’s crop dictates the size.
  • minMp (required): The pixel-count threshold for upscaling (default 3,000,000). Pass null to use the default.
  • minWidth (required): The minimum width of the recorded video. Pass null to use the default.
  • minHeight (required): The minimum height of the recorded video. Pass null to use the default.
  • fileName (optional): The base name of the saved clip. Defaults to the device name.
client.startRecording(
  shouldInterpolate = null, // Use the default interpolation behaviour
  minMp = null, // Use the default megapixels
  minWidth = null, // Use the default width
  minHeight = null, // Use the default height
  fileName = "Front Door" // The base name of the saved clip
)

On a multi-stream camera (device.hasMultiStream()) one clip is recorded per sensor and each file name is suffixed with the sensor number; otherwise one full-frame clip. If the stream has no video track yet the call is ignored and isRecording stays false.


Stop a recording

To stop recording and save the clips, The following method can be used:

  • onSaved (optional): Receives the number of clips that were saved (outputs with bytes written), on the main thread once the encoders drain. isRecording flips to false and auto-disconnect resumes immediately on stopRecording(), before the callback.
client.stopRecording { savedCount ->
  // The number of clips written to the gallery
}

The callback reports how many clips were saved, not where they are. Because the SDK writes into the gallery as it records, there are no files to move or upload afterwards, and no file handles are returned.


Observe the recording state

To know whether a recording is in progress, the following property can be used:

viewModelScope.launch {
  client.isRecording.collectLatest { isRecording ->
    if (isRecording) {
      // A recording is in progress
    } else {
      // No recording is in progress
    }
  }
}

Most apps never need this. If you drive WebRtcRecorder directly instead of going through LiveStreamClient, you are responsible for creating and publishing the gallery entries yourself.

  • createGalleryVideoTarget reserves a pending entry in the gallery and opens a descriptor to it. It returns null if the entry could not be created.
  • publishGalleryVideoTarget closes the descriptor and makes the entry visible to the user.
  • discardGalleryVideoTarget closes the descriptor and deletes the entry, for a recording that was abandoned.
val target = context.createGalleryVideoTarget("Front Door.mp4")
if (target != null) {
  val output = WebRtcRecorder.SensorOutput(
    crop = crop, // The region of the frame to record
    outputDescriptor = target.descriptor // Write into the gallery entry
  )
  // Record using the output, then publish the entry once recording completes
  context.publishGalleryVideoTarget(target)
}

A SensorOutput needs either an outputFile or an outputDescriptor, and it fails to construct if both are missing.


Capture a snapshot

To save a still from the live view into the gallery through MediaStore, The following method can be used. It captures from every player, so a dual-lens camera yields one image per sensor; the file is <fileName>.jpeg.

  • fileName (required): The base name of the image.
  • shouldInterpolate, minMp, minWidth, minHeight: The same scaling options as startRecording; pass null for the defaults.
  • appPicturesPath (required): A MediaStore relative path under which the JPEG is published, e.g. "Pictures/MyApp" — not an absolute filesystem path.
  • saveListener (optional): Called once per player with true if a frame was available to snapshot (write failures are not reported), false if no frame has been rendered yet.
client.saveSnapshot(
  fileName = "Front Door",
  shouldInterpolate = null,
  minMp = null,
  minWidth = null,
  minHeight = null,
  appPicturesPath = "Pictures/MyApp",
  saveListener = { saved -> }
)

This site uses Just the Docs, a documentation theme for Jekyll.