5

I'm working on a screen-capture program. Currently, it's saving the output of the window as webm. I'm wondering if it's possible to save it as GIF instead using MediaRecorder, which is part of the native MediaStream Recording API.

Or do I have to rely on an external plugin such as FFMPEG to do the conversion for this? Would be neat to be able to save it directly as GIF.

When I'm changing the mimeType to image/gif; codecs=vp9 and the output of the file to .gif. The recording isn't producing any output (no errors either). Since MediaRecorder is quite new as of writing this, there isn't very much information available. Mozilla Docs

This is a snippet of my code, class is called Recorder:

public static readonly mimeType: string = "video/webm; codecs=vp9";
public mediaRecorder?: MediaRecorder;
public videoElement: HTMLVideoElement = <HTMLVideoElement>document.querySelector("video");
...

async selectSource(source: Electron.DesktopCapturerSource): Promise<any> {
    ...
    const stream = await navigator.mediaDevices.getUserMedia(<MediaStreamConstraints>constraints);
    this.videoElement.srcObject = stream;

    const streamOptions = { mimeType: `${Recorder.mimeType}` };

    this.mediaRecorder = new MediaRecorder(stream, streamOptions);
    this.mediaRecorder.ondataavailable = () => this.storeAvailableData;
    this.mediaRecorder.onstop = () => this.saveRecording();
}

storeAvailableData(e:any): void {
    console.log("video data available");
    this.recordedChunks.push(e.data);
}

async saveRecording(): Promise<any> {
    //blob is of type any due to @typings not yet updated.
    const blob:any = new Blob(this.recordedChunks, {
        type: `${Recorder.mimeType}`
    });

    const buffer = Buffer.from(await blob.arrayBuffer());

    const { filePath } = await this.dialog.showSaveDialog({
        buttonLabel: "Save video",
        defaultPath: `vid-${Date.now()}.webm`
    });

    if (filePath) {
        writeFile(filePath, buffer, () => console.log("video saved!"));
    }
}

I'm using Electron.js - but this is not a Electron-related problem (as far as I can tell).


Update 2021: Supported codecs

Docs/spec is now somewhat more complete. However, GIF option is still not available.

VC.One
  • 14,790
  • 4
  • 25
  • 57
Joel
  • 5,732
  • 4
  • 37
  • 65
  • https://github.com/jnordberg/gif.js might help you, its a library for recording gif files in js. You can grab images from the video source 30 times per second and push them into a gif.js instance. – Lukas Bach Mar 11 '20 at 13:31
  • @LukasBach Thanks, if MediaRecorder gets ruled out, I might look at other alternatives. Now I'm specifically asking regarding MediaRecorder. – Joel Mar 11 '20 at 13:35
  • @Joel I think It cannot be done with MediaRecorder API, as you have mentioned it needs to be done with an external tool like ffmpeg. If possible you can download the ffmpeg binary and invoke it within electron for the conversion – Vignesh Nandakumar Jun 20 '22 at 16:21
  • @VigneshNandakumar It wasn't I who started the bounty – Joel Jun 21 '22 at 07:20
  • @[James](https://stackoverflow.com/users/626632/james) I added the `html5` tags incase that helps to get you a faster answer. PS: In 2022 you have options like finding some JS-based Animated GIF encoder, or run a C++ Gif encoder via WASM, or if you're using a Chromium based browser there is also the **web codecs** API to investigate. See S.O's [webcodec](https://stackoverflow.com/questions/tagged/webcodecs?tab=Newest) tag to check how others use it (is supported in Chrome/Edge only for now) – VC.One Jun 22 '22 at 06:36
  • Since you already recorded the video you can play the video back to a canvas then record the canvas as a gif. I know this is an extra step but it avoid having to use a tool like ffmpeg https://dev.to/ndesmic/how-to-record-a-canvas-element-and-make-a-gif-4852 – Woodsy Jun 23 '22 at 16:25
  • @Woodsy You linked to a page that's using ffmpeg – Joel Jun 23 '22 at 22:34
  • This library came up https://github.com/kettek/MediaStream-GifRecorder. Maybe it could help you? – crstn.udrea Jun 24 '22 at 09:50
  • @Joel I had a few tabs open looking for solutions on how to save a canvas as a gif and posted the wrong link. Looks like this was solved though. Sorry about that – Woodsy Jun 24 '22 at 14:27

1 Answers1

3

image/gif mime-type is not supported in MediaRecorder.

You will need a Javascript library to encode as Animated GIF:
https://github.com/mattdesl/gifenc

You can also try MediaStreamRecorder instead of using native MediaRecorder:
https://github.com/intercom/MediaStreamRecorder/blob/master/demos/gif-recorder.html

note from MediaStreamRecorder docs:

"MediaStreamRecorder can record audio as WAV and video as either WebM or animated gif on Chrome browser."

Maybe this helps.

Regards, omi

VC.One
  • 14,790
  • 4
  • 25
  • 57
omi
  • 718
  • 3
  • 10
  • You can use gifencoder in your current code. But would require few changes in your code. Play media stream to video --> Draw video frames to canvas --> Add canvas frame to gif encoder frame --> generate gif blob at last. Kindly check this code https://github.com/intercom/MediaStreamRecorder/blob/master/VideoStreamRecorder/GifRecorder.js – omi Jun 24 '22 at 10:32