Guangzhou Lanjing Sharing—3 JavaScript plug-ins necessary for programmers to make your videos more practical

Today, the editor of Guangzhou Lanjing shares with you some dry goods, 3 JavaScript plug-ins that programmers must have to make your videos more practical.
Right from the start of this technical article, I tend to utilize screen captures encoded in Graphics Interchange Format (GIF) format to minimize extra chunks of text description. For example, in articles that are more oriented towards web development content such as:

In this case, I always find it beneficial to embed animated GIFs to demonstrate any usage of open source tools I create:

insert image description here

Given that Microsoft Powerpoint's built-in screen recording feature is easy to access though, it's easy to do your own screen recording to output screenshots, but I feel like a more rewarding area to explore would be - easy access to tools for converting video to screenshots (.mp4, .avi, etc.) to .GIF image files.

— NOTE: By convention, if you are rendering short animations (≤ 30 seconds), GIF files are more appropriate.

Build Video to GIF Maker with GIFEncoder.js

In order to build browser utilities like this:
insert image description here

These 3 JavaScript plugins are required:

GIFEncoder.js
LZWEncoder.js
NeuQuant.js
FYI: These plugins were originally retrieved from the GitHub repo jsgif by GitHub user Kevin Kwok (the creator).

Overview of Video to GIF Conversion

Prerequisites: Included in the above 3 files + b64.js as follows:

<script type="text/javascript" src="LZWEncoder.js"></script>
<script type="text/javascript" src="NeuQuant.js"></script>
<script type="text/javascript" src="GIFEncoder.js"></script>
<script type="text/javascript" src="b64.js"></script>

Technical implementation - 4 steps in total

Step (1): Upload a video clip (≤30 seconds)

So, in the HTML code, include a simple user input interface:


Mark the event handler (onchange) above and proceed to initialize the FileReader instance in JavaScript:

inputVideoClipFile.onchange = function(uploadFle) {
  let file = inputVideoClipFile.files[0];
let fileName=file.name;
  let fileSize=(file.size/1024).toFixed(2);
  let fileType=file.type;
let fileredr = new FileReader();
fileredr.onload = function (fle) {
    var b64Str=fle.target.result;
}; // end file-reader onload
  fileredr.readAsDataURL(file);
};

Note that the new FileReader() instance calls readAsDataURL, so the content of the video file assigned to b64Str is read as a Base64 string.

Retrieve video file information from a file object for later display.

Step (2): Processing video binary data and extracting frames, there are two main parts to consider:

Part I. Preview video content for display by creating DOM elements and assigning corresponding properties in JavaScript.

// rendered as <video></video> in HTML code
var videoObj = document.createElement('video');
var displayedHeight=500;
if(videoObj.canPlayType(fileType)) {
  videoObj.setAttribute('id','inputVideo');
  videoObj.setAttribute('src', b64Str);
  videoObj.setAttribute('height', displayedHeight);
}

Note that b64Str is the video file data read by FileReader() in the previous steps.

The second part, frame extraction - each video frame refers to an image snapshot of the clip at a unique timestamp.

Since GIF files are created by merging a sequential set of images, for each temporal graphics update of the video, a frame with embedded image data needs to be extracted for subsequent GIF creation process.

While the image data needed for each video frame cannot be extracted directly from the DOM element, it is possible to render the preview content in the element onto the frame image data extraction.

Next, create an element in JavaScript and assign it the appropriate attributes (something like):

var vidHeight=videoObj.videoHeight;
var vidWidth=videoObj.videoWidth;
var bitmap = document.createElement('canvas');
bitmap.setAttribute('id', 'bitmap');
bitmap.setAttribute('width', vidWidth);
bitmap.setAttribute('height', vidHeight);

Note that vidWidth and vidHeight are retrieved from . (These are the original dimensions of the clip.)

The next few lines of code refer to and based on the 'id' attribute tagged to each element:

const inputVideo=document.getElementById('inputVideo');
const bitmapCanvas=document.getElementById('bitmap');
const bitmapCtx = bitmapCanvas.getContext('2d');
inputVideo.muted = true;
inputVideo.loop = false;
inputVideo.autoplay=true;
const background = () => {
  bitmapCtx.fillStyle = '#FFFFFF';
  bitmapCtx.fillRect(0, 0, vidWidth, vidHeight);
};

Since the video is set to autoplay, when the play event is emitted, this triggers the execution of background(), which not only fills the GIF background with white, but also sets the size of each frame drawn onto the canvas element:

const step = async() => {
  let bgStatus=await background();
  await new Promise(resolve => {
    bitmapCtx.drawImage(inputVideo, 0, 0, vidWidth, vidHeight);
    frameB64Str = bitmapCanvas.toDataURL();
    resolve();
  });
  window.requestAnimationFrame(step);
};
inputVideo.addEventListener('play', () => {
  step();
  window.requestAnimationFrame(step);
});

window.requestAnimationFrame(step) accepts a callback function (ie step()) to process the image data for each frame.

bitmapCtx.drawImage() proceeds to render each image snapshot to the canvas, so that bitmapCanvas.toDataURL() returns the base64-encoded image of each snapshot.

Step (3): Merge all image snapshots sequentially

Finally, the JS plug-in GIFEncoder.js is implemented. Using the same code snippet as above, the lines in bold below refer to the GIFEncoder instance that captures each dataframe embedded in .

const encoder = new GIFEncoder(vidWidth, vidHeight);
encoder.setRepeat(0);
encoder.setDelay(500);
const step = async() => {
  let bgStatus=await background();
  await new Promise(resolve => {
    bitmapCtx.drawImage(inputVideo, 0, 0, vidWidth, vidHeight);
    frameB64Str = bitmapCanvas.toDataURL();
    encoder.addFrame(bitmapCtx);
    resolve();
  });
  window.requestAnimationFrame(step);
};
inputVideo.addEventListener('play', () => {
  encoder.start();
  step();
  window.requestAnimationFrame(step);
});

When the uploaded video finally plays its full duration, a finish event should be emitted where the GIFEncoder calls the method finish():

inputVideo.addEventListener('ended', () => {
  encoder.finish();
});

Step (4): Create GIF with GIFEncoder

To extract the merged version of all frames (i.e. the GIF output) from the encoder, the following JavaScript snippet needs to be implemented:

var fileType='image/gif';
var readableStream=encoder.stream();
var binary_gif=readableStream.getData();
var b64Str='data:'+fileType+';base64,'+encode64(binary_gif);

encode64() is a method in b64.js that converts stream data captured by GIFEncoder into Base64 format.

b64Str references the data encoded for a GIF file by merging all frames present in the GIFEncoder. So, in the HTML code, go ahead and include: ${fileName}to preview the output GIF file.

Finally, create a download link for the GIF file, as follows:

let dwnlnk = document.createElement('a');
dwnlnk.download = fileName;
dwnlnk.innerHTML = ` <small>Save</small>`;
dwnlnk.className = 'btn btn-outline-dark';
dwnlnk.href = b64Str;

Summarize

Although, there is room for further exploration of the customizable tweaking of the output GIF files in GIFEncoder.js, what this article presents is a basic, lightweight approach to converting video clips to GIF files.

Finally: The content of the article is reproduced on other platforms.

Guess you like

Origin blog.csdn.net/qq_43230405/article/details/126549073