hypertrons / hypertrons-crx

A browser extension for insights into GitHub projects and developers.
https://crx.hypertrons.io
Apache License 2.0
344 stars 98 forks source link

[Feature] export racing bar animation as video #724

Open tyn1998 opened 1 year ago

tyn1998 commented 1 year ago

Description

Users want to share Contributors Activity Racing Bar in the form of video. It is a good idea and also a chance to spread Hypercrx, OpenDigger and X-lab. We should support this feature :)

Watermark: "Powered by OpenDigger and Hypercrx" or "Powered by X-lab"

andyhuang18 commented 1 year ago

I think this is a great idea! ! Because Racing Bar is also a very interesting feature. Hi~ @lhbvvvvv , can you give it a try?

l1tok commented 1 year ago

I think this is a great idea! ! Because Racing Bar is also a very interesting feature. Hi~ @lhbvvvvv , can you give it a try?

Ok, I can try it.

tyn1998 commented 1 year ago

Hi @lhbvvvvv, Do you have any ideas to share with us regarding the implementation of this feature?

l1tok commented 1 year ago

I thought about using RecordRTC.js to do this, I did a simple test in my own html file, and now I'm wondering if I can use this in hypercrx.

tyn1998 commented 1 year ago

now I'm wondering if I can use this in hypercrx.

If the library can help you to implement the feature, then there you go! A draft PR is also welcomed.


Hi @lhbvvvvv, I have also some information generated by GPT for you. Hope it helps :)

Me:I use ECharts to implement a racing bar chart, now I want to export the animation as a video and I hope the export process entirely happens in the browser, How can I achieve this? ChatGPT3.5:To export the animation of a racing bar chart created using ECharts as a video entirely within the browser, you can follow these steps:

  1. Create the racing bar chart using ECharts and configure the animation as desired.

  2. Use the ECharts on method to listen for the finished event of the animation. This event is triggered when the animation is complete.

myChart.on('finished', function() {
  // Export the chart animation as a video
});
  1. Inside the event handler function, you can utilize the canvas element and the captureStream() method to capture the chart animation frames.
const canvas = document.querySelector('canvas');
const stream = canvas.captureStream();
  1. Use the MediaRecorder API to record the captured frames and export them as a video file.
const chunks = [];

const mediaRecorder = new MediaRecorder(stream, {
  mimeType: 'video/webm; codecs=vp9'
});

mediaRecorder.ondataavailable = function(event) {
  chunks.push(event.data);
};

mediaRecorder.onstop = function() {
  const blob = new Blob(chunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);

  // Create a video element and set the source to the recorded video
  const video = document.createElement('video');
  video.src = url;

  // Download the video
  const a = document.createElement('a');
  a.download = 'chart_animation.webm';
  a.href = url;
  a.click();

  // Clean up
  URL.revokeObjectURL(url);
};

mediaRecorder.start();
  1. Start the media recorder when the animation finishes.
myChart.on('finished', function() {
  mediaRecorder.start();
});

// Stop the media recorder after desired duration
setTimeout(function() {
  mediaRecorder.stop();
}, 5000); // Set the duration as desired or based on the chart animation time

With these steps, the racing bar chart animation will be captured and exported as a video file within the browser.

Me:Why start the record process after the animation finished? I do want to record the animation! ChatGPT3.5:Apologies for the misunderstanding. If you want to start recording the animation immediately without waiting for it to finish, you can skip the 'finished' event listener and start the media recorder as soon as the chart is rendered. Here's an updated code example:

// Create the racing bar chart using ECharts and configure the animation as desired
const myChart = echarts.init(document.getElementById('chart'));

// ...

// Capture the canvas element
const canvas = document.querySelector('canvas');
const stream = canvas.captureStream();

// Start the media recorder
const chunks = [];
const mediaRecorder = new MediaRecorder(stream, {
  mimeType: 'video/webm; codecs=vp9'
});

mediaRecorder.ondataavailable = function(event) {
  chunks.push(event.data);
};

// Start recording immediately
mediaRecorder.start();

// Stop the media recorder after desired duration or when the animation is complete
setTimeout(function() {
  mediaRecorder.stop();
}, 5000); // Set the duration as desired or based on the chart animation time

// Handle the stop event
mediaRecorder.onstop = function() {
  const blob = new Blob(chunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);

  // Create a video element and set the source to the recorded video
  const video = document.createElement('video');
  video.src = url;

  // Download the video
  const a = document.createElement('a');
  a.download = 'chart_animation.webm';
  a.href = url;
  a.click();

  // Clean up
  URL.revokeObjectURL(url);
};

With this modification, the recording process will start immediately upon rendering the chart, capturing the animation frames until the desired duration or when manually stopped.

Me:I want to start the recording process after clicking a start button and finish the record process after the echarts animation finished. ChatGPT3.5:Understood. To achieve this, you can implement the following steps:

  1. Add a start button to your HTML markup.

    <button id="startButton">Start Recording</button>
  2. Modify the JavaScript code to start the recording process when the start button is clicked.

    
    const startButton = document.getElementById('startButton');

// Create a flag to track if recording has started let recordingStarted = false;

// Event listener for the start button startButton.addEventListener('click', function() { // Start the recording only if it has not already started if (!recordingStarted) { recordingStarted = true;

// Capture the canvas element
const canvas = document.querySelector('canvas');
const stream = canvas.captureStream();

// Start the media recorder
const chunks = [];
const mediaRecorder = new MediaRecorder(stream, {
  mimeType: 'video/webm; codecs=vp9'
});

mediaRecorder.ondataavailable = function(event) {
  chunks.push(event.data);
};

// Start recording
mediaRecorder.start();

// Stop the media recorder after the animation finishes
myChart.on('finished', function() {
  if (recordingStarted) {
    recordingStarted = false;
    mediaRecorder.stop();
  }
});

// Handle the stop event
mediaRecorder.onstop = function() {
  const blob = new Blob(chunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);

  // Create a video element and set the source to the recorded video
  const video = document.createElement('video');
  video.src = url;

  // Download the video
  const a = document.createElement('a');
  a.download = 'chart_animation.webm';
  a.href = url;
  a.click();

  // Clean up
  URL.revokeObjectURL(url);
};

} });



With this code, the recording process will start only when the start button is clicked. The recording will continue until the ECharts animation finishes or until the stop button is clicked.

Me:The demo code looks good, please also give the explanation of the API used in the code
ChatGPT3.5:Certainly! Here's an explanation of the APIs used in the code:

1. `querySelector`: This method is used to select the first element that matches a specified CSS selector. In the code, it is used to select the `<canvas>` element on which the ECharts chart is rendered.

2. `captureStream()`: This method is used to capture the contents of a DOM element, such as a `<canvas>`, as a media stream. In the code, it is used to capture the frames of the chart animation as a stream.

3. `MediaRecorder`: This API allows you to record media streams, such as the one captured from the `<canvas>` element. It provides methods and events to control and handle the recording process. In the code, it is used to record the captured stream as a video.

   - `new MediaRecorder(stream, options)`: This creates a new `MediaRecorder` instance, where `stream` is the media stream to record and `options` specify the desired configuration, such as the MIME type and codecs for the recorded video.

   - `MediaRecorder.ondataavailable`: This event is triggered whenever new recorded media becomes available. In the code, it is used to handle the availability of recorded video chunks and store them in an array.

   - `MediaRecorder.onstop`: This event is triggered when the recording is stopped. In the code, it is used to handle the stop event and perform further actions, such as creating a video element, downloading the recorded video, and cleaning up.

   - `MediaRecorder.start()`: This method starts the recording process.

   - `MediaRecorder.stop()`: This method stops the recording process.

4. `URL.createObjectURL()`: This method creates a DOMString representing a URL object from a `Blob` or `File` object. In the code, it is used to generate a URL for the recorded video blob, allowing it to be set as the source of a video element or used for downloading.

5. `addEventListener()`: This method is used to register an event listener on a DOM element. In the code, it is used to listen for the click event on the start button.

I hope this explanation clarifies the usage of the APIs in the code. Let me know if you have any further questions!
l1tok commented 1 year ago

Thanks @tyn1998 for your help, it was very useful for me. I have a question how to get the 'finished' status of the chart. I also asked the gpt but didn't get a useful answer.

    // Stop the media recorder after the animation finishes
    myChart.on('finished', function() {
      if (recordingStarted) {
        recordingStarted = false;
        mediaRecorder.stop();
      }
    });
tyn1998 commented 1 year ago

@lhbvvvvv you may refer to the docs of ECharts API: https://echarts.apache.org/zh/api.html#events.finished

I guess the event will be fired after each animation triggered by each setOption. So only the last finished event should be used to stop recording.

l1tok commented 1 year ago

I encountered this problem when the video recording was finished. image

tyn1998 commented 1 year ago

Seems like a trouble, could you create a draft PR for further discussion on implementation?

l1tok commented 1 year ago

I encountered some network problems and couldn't push the code. Then I will tweak the code and submit the pr draft.

tyn1998 commented 1 year ago

@lhbvvvvv If you are using Mac, this might help:

image