DeepMedia logodeepmedia

Camera SDK

Version 0.8.5

Search

Choose platform

Other versions of this page

Recording

The SDK lets you capture MP4 videos by merging the camera stream with audio stream from the microphone (remember to ask for permissions!). The quality of the results can be set with fine-grained APIs and is only limited by the capabilities of the current device's hardware, in terms of audio/video encoders, sensor resolution and frame rate, microphone availability and more.

⚠️

Make sure you declare CameraFeature.VideoCameraFeature.video during manager initialization.

For anything video-related, you will interact with the manager's CameraRecorder:

kotlin logokotlin
val recorder: CameraRecorder = manager.recorder
kotlin logokotlin
let recorder: CameraRecorder = manager.recorder

Under the hood, the SDK uses a custom encoding and muxing pipeline that allows features that are normally hard to achieve, for example:

  • ability to switch cameras while recording
  • support for fast start MP4s, that is, streaming-friendly MP4 files that expose video metadata at the beginning of the file

Codecs

The following audio (AudioCodec) and video (VideoCodec) codecs are supported.

TypeCodecDescription
VideoCodecH264.h264H264 Advanced Video Coding (AVC), Main Profile.
VideoCodecH264Baseline.h264BaselineH264 Advanced Video Coding (AVC), Baseline Profile.
VideoCodecH264High.h264HighH264 Advanced Video Coding (AVC), High Profile.
VideoCodecH265.h265H265 High Efficiency Video Coding (HEVC), Main Profile.
AudioCodecAac.aacLow Complexity (LC) AAC codec.
AudioCodecAacLD.aacLDLow Delay (LD) AAC codec.
AudioCodecAacELD.aacELDEnhanced Low Delay (ELD) AAC codec.
AudioCodecAacHE.aacHEHigh Efficiency (HE) AAC codec.

Recording Quality

The first thing you may want to do is decide how "good" the final recording should be. It's not recommended to use settings of a higher quality than what's needed, as video recordings can easily bloat in size.

The AudioProfile and VideoProfile classes encapsulate all sorts of settings related to, respectively, audio and video streams, in both their raw (right after acquisition) and encoded forms. Their meaning is pretty straightforward, for example:

  • AudioProfile.channels represents the number of audio channels to be present in the output file
  • VideoProfile.frameRate represents the number of video frames per second

After you determine the profiles you want (using one of the two techniques below), they must be passed to the recorder:

kotlin logokotlin
val recorder: CameraRecorder = manager.recorder recorder.audioProfile.value = myAudioProfile // or null to disable recorder.videoProfile.value = myVideoProfile
swift
let recorder: CameraRecorder = manager.recorder recorder.audioProfile = myAudioProfile // or nil to disable recorder.videoProfile = myVideoProfile

Using presets

Presets are a collection of profiles that are tailored to the current device and are known to be supported. They are the easiest way for you to configure profiles. For video presets:

kotlin logokotlin
val codec: VideoCodec = VideoCodec.H264 // Or H265 val presets: VideoPresets = recorder.presets(codec) ?: return // codec not supported // Choose profile among: .p360, .p480, .p540, .p720, .p1080, .p2160 val profile: VideoProfile = presets.p1080 ?: return // 1080p not supported: fallback to something else? recorder.videoProfile.value = profile
swift
let codec: VideoCodec = .h264 // Or h265 guard let presets: VideoPresets = recorder.presets(codec: codec) else { return } // codec not supported // Choose profile among: .p360, .p480, .p540, .p720, .p1080, .p2160 guard let profile: VideoProfile = presets.p1080 else { // 1080p not supported: fallback to something else? return } recorder.videoProfile = profile

For audio presets, the logic is exactly the same, but the presets fields are called, from highest quality to lowest, musicHq, music, musicLq, voiceHq, voice, and voiceLq.

Using custom profiles

In case you want to customize profiles with your own settings you must follow a two-steps procedure:

  1. Create a Stub (AudioProfile.Stub or VideoProfile.Stub) with your settings
  2. Transform into a real profile with makeProfile. This checks whether it's supported or not and possibly adjusts some of the parameters

After that, the profile can be passed to CameraRecorder as already shown previously. Check the following example for video:

kotlin logokotlin
val stub: VideoProfile.Stub = VideoProfile.Stub( codec = VideoCodec.H264, majorSize = 1080, minorSize = null, // let the engine choose bitRate = 16000000, frameRate = 60 ) val profile: VideoProfile = recorder.makeProfile(stub) ?: return // Not supported!
swift
let stub: VideoProfile.Stub = VideoProfile.Stub( codec: .h264, majorSize: 1080, minorSize: nil, // let the engine choose bitRate: 16000000, frameRate: 60 ) guard let profile: VideoProfile = recorder.makeProfile(stub: stub) else { return } // Not supported!

When one size is specified and there is not, you can also pass an aspectRatio (like 16/9) and let the engine figure out the other dimensions based on that.

Recording APIs

Once profiles are chosen (or if you decide to use default profiles, for what it's worth), you can start recording.

⚠️

Switching between cameras while recording is allowed: the SDK will seamlessly switch the video source from one sensor to the other and you'll see no artifacts in the final video.

Start and stop

To start recording, use CameraRecorder.record(). This is a async / suspending function with a single URL / String parameter which should point to a writable, empty location on disk.

The function must be called in a dedicated Task / coroutine because it represents the whole recording operation:

  • once the function returns, the video is ready
  • if it throws, recording has failed
kotlin logokotlin
scope.launch { try { recorder.record(myFilePath) // Recording complete! } catch (e: Throwable) { // Something went wrong. } }
swift
Task { do { try await recorder.record(at: myURL) // Recording complete! } catch { // Something went wrong. } }

To stop recording, simply call recorder.stop().

Pause and resume

While recording is ongoing, you can also toggle between a paused and recording state using the pause() and resume() APIs:

kotlin logokotlin
// CameraRecorder APIs suspend fun pause() { ... } suspend fun resume() { ... }
swift
// CameraRecorder APIs func pause() async throws { ... } func resume() async throws { ... }

Subscribe to the DeepMedia Newsletter

The latest news about DeepMedia products, open source projects and software development at our company.

By clicking “Subscribe”, you agree that DeepMedia may use your email address to send you newsletters, including commercial communications, and to process your personal data for this purpose. You agree that DeepMedia may process said data using third-party services for this purpose in accordance with the DeepMedia Privacy Policy. You can revoke this consent at any time using the unsubscribe link included in each email or by writing at contact@deepmedia.io.