videokit-ai / videokit

Low-code, cross-platform media SDK for Unity Engine. Register at https://videokit.ai
https://videokit.ai
Apache License 2.0
107 stars 14 forks source link

How to capture a screenshot using JPEG recorder? #132

Closed thesanketkale closed 4 months ago

thesanketkale commented 4 months ago

Hi @olokobayusuf,

I am looking for a way to capture one photo of the 3D scene which will be saved to cache storage and could be shared later. How should I do it with the latest API changes?

In version 0.0.17 of VideoKit, I achieved this using the JPEG recorder in which I captured JPEG image sequences for 1 second and then took the last image in the image sequence as the final image. But this appears to be broken in the latest version 0.0.19 of VideoKit as I am getting the below exceptions while recording the JPEG image sequences:

ArgumentException: Value does not fall within the expected range.

Below is the code I currently use to capture the image:

private IEnumerator CaptureScreenShot()
{
    JpegRecorder.videoMode = VideoKitRecorder.VideoMode.Camera;
    JpegRecorder.resolution = VideoKitRecorder.Resolution.Screen;

    JpegRecorder.watermarkMode = VideoKitRecorder.WatermarkMode.None;
    JpegRecorder.audioMode = VideoKitRecorder.AudioMode.None;
    JpegRecorder.format = MediaRecorder.Format.JPEG;

    JpegRecorder.recordingAction = VideoKitRecorder.RecordingAction.Custom;
    JpegRecorder.OnRecordingCompleted.RemoveAllListeners();
    JpegRecorder.OnRecordingCompleted.AddListener(OnRecordingCompleted);

    // Set cameras
    List<Camera> cameras = new List<Camera>();
    cameras.Add(MainCamera);
    cameras.Add(WatermarkCamera);

    JpegRecorder.cameras = cameras.ToArray();
    JpegRecorder.StartRecording();

    yield return new WaitForSeconds(1f);

    JpegRecorder.StopRecording();
}

private void OnRecordingCompleted(MediaAsset mediaAsset)
{
    MediaAsset lastMediaAsset = mediaAsset.assets[mediaAsset.assets.Count - 1];
    SaveImage(lastMediaAsset.path);
}

Do you have a better approach to this with the latest API or will this approach work for my case? If this approach is ok, then how should I fix the exception?

olokobayusuf commented 4 months ago

Hey @thesanketkale what platform are you getting this error on?

thesanketkale commented 4 months ago

It was in Unity Editor on Windows 11. But since I replaced this implementation with the one you shared on discord, I am not getting any error now. We can close this for now.

olokobayusuf commented 4 months ago

@thesanketkale can you share the implementation that works now? I'm considering adding it into VideoKit under VideoKitRecorder.CaptureScreenshot.

thesanketkale commented 4 months ago

Sure here is the working code to capture a screenshot using VideoKit API.

private CameraSource source;

private async void CaptureScreenShotAsync(int width, int height, Camera[] cameras)
{
    var recorder = await MediaRecorder.Create(MediaRecorder.Format.JPEG, width, height);
    var clock = new RealtimeClock();
    source = new CameraSource(
        recorder.width,
        recorder.height,
        async pixelBuffer =>
        {
            recorder.Append(pixelBuffer); // commit the pixel buffer
            source.Dispose(); // stop generating frames immediately
            var sequenceAsset = await recorder.FinishWriting();
            var imageAsset = sequenceAsset.assets[0];
            OnRecordingCompleted(imageAsset.path);
        },
        clock,
        cameras
    );
}
olokobayusuf commented 4 months ago

Thank you!