<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Mark – IMG.LY Blog</title><description>Let me help you integrate into the “New World” and show you amazing features that you may not know. I love to write about Programming, IT-sphere, and Web 3.0</description><link>https://img.ly/blog/author/mark/</link><language>en-us</language><image><url>https://img.ly/apple-touch-icon.png</url><title>Mark – IMG.LY Blog</title><link>https://img.ly/blog/author/mark/</link></image><atom:link href="https://img.ly/blog/author/mark/rss.xml" rel="self" type="application/rss+xml"/><generator>Astro</generator><lastBuildDate>Fri, 19 Jun 2026 11:25:53 GMT</lastBuildDate><ttl>60</ttl><item><title>Comparing the Top 5 Open Source JavaScript Image Manipulation Libraries</title><link>https://img.ly/blog/the-top-5-open-source-javascript-image-manipulation-libraries/</link><guid isPermaLink="true">https://img.ly/blog/the-top-5-open-source-javascript-image-manipulation-libraries/</guid><description>Learn the difference between five major image manipulation libraries and choose the right one for you!</description><pubDate>Tue, 27 Sep 2022 13:29:03 GMT</pubDate><content:encoded>&lt;p&gt;Image Manipulation Libraries (IML) are used to perform various manipulation functions on images: you can increase the brightness of an image, add saturation or filters, crop and resize, and more valuable features that will help you to do almost everything and turn your web browser into an Adobe Lightroom!&lt;br&gt;
We have included libraries for every significant image manipulation task, from simple, low-level operations such as filters, brightness, and saturation to single-purpose libraries for cropping or image composition. To finish up, we wandered into the realm of testing images, since no image manipulation application is complete without a reliable way to test results.&lt;/p&gt;
&lt;h2 id=&quot;sharp&quot;&gt;Sharp&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nodejsera.com/resize-image-using-sharp-nodejs.html#overview&quot;&gt;Sharp&lt;/a&gt; is a high-performance Node.js image processing library to resize different image formats such as JPEG, PNG, WebP, AVIF, SVG, and TIFF. The typical use case for this high-speed Node.js module is to convert large images in standard formats to smaller, web-friendly images.&lt;/p&gt;
&lt;p&gt;Sharp is helpful only if you want to resize a giant file or a variety of them. If, on the other hand, you only want to resize a single small image, then you probably shouldn’t use it. Instead, ordinary HTML and vanilla JavaScript will be more beneficial. Sharp is taking full advantage of multiple CPU cores and L1/L2/L3 cache, allowing you to resize and compress your images much more quickly.&lt;/p&gt;
&lt;h3 id=&quot;use-cases&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;I used it to resize a whole NFT Collection with a size of over 80Gb, which after compression came out at circa 10Gb. So again, if you would like to use it for resizing several large images, then it’s the best choice for you - you’ll do it in the fastest and most efficient way.&lt;/p&gt;
&lt;h3 id=&quot;example&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;You can install this library by using the command below:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; sharp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how you would resize an image using sharp:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; sharp&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;sharp&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; fs&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;fs&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;sharp&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;yellow.png&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;rotate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;180&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;resize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;toBuffer&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    fs.&lt;/span&gt;&lt;span&gt;writeFileSync&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;yellow.png&apos;&lt;/span&gt;&lt;span&gt;, data);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(err);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;&quot;&gt;&lt;/h2&gt;
&lt;p&gt;Cropper.js&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/fengyuanchen/cropperjs&quot;&gt;Cropper.js&lt;/a&gt; is another popular JavaScript library for image manipulation. You can use it to crop your images in all possible ways, change aspect ratio, rotate, zoom and work with canvas data. &lt;a href=&quot;https://github.com/fengyuanchen/cropperjs&quot;&gt;Cropper.js&lt;/a&gt; is the right choice for cropping without any extra features.&lt;/p&gt;
&lt;h3 id=&quot;use-cases-1&quot;&gt;Use Cases&lt;/h3&gt;
&lt;p&gt;You can use its flexible API to create a custom image cropping UI in your web app allowing your users to adjust photos to the correct size and aspect ratio. It will be more efficient because it requires almost nothing, doesn’t have any useless features, and is very optimized for cropping!&lt;/p&gt;
&lt;h3 id=&quot;example-1&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;This library can be installed with the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install cropperjs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Cropper &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;cropperjs&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; image&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;image&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; cropper&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Cropper&lt;/span&gt;&lt;span&gt;(image, {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  aspectRatio: &lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt; /&lt;/span&gt;&lt;span&gt; 9&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  crop&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.x);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.y);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.width);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.height);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.rotate);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.scaleX);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(event.detail.scaleY);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check out the Cropper.js &lt;a href=&quot;https://fengyuanchen.github.io/cropperjs/&quot;&gt;demo&lt;/a&gt;, click on any property that you want to apply to your image and see the result instantly.&lt;/p&gt;
&lt;p&gt;For an in-depth guide on how to add image cropping to your React app, check out our &lt;a href=&quot;https://img.ly/blog/how-to-crop-an-image-in-react-with-react-image-crop/&quot;&gt;guide on using&lt;/a&gt; &lt;a href=&quot;https://img.ly/blog/how-to-crop-an-image-in-react-with-react-image-crop/&quot;&gt;&lt;code&gt;react-image-crop&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;merge-images&quot;&gt;Merge Images&lt;/h2&gt;
&lt;p&gt;Working with the canvas can be slightly tedious, especially when you need the canvas context to do relatively simple things like merging a few images. &lt;a href=&quot;https://github.com/lukechilds/merge-images&quot;&gt;Merge Images&lt;/a&gt; abstracts all repetitive tasks into simple function calls. It’s a wrapper around the Canvas API, abstracting its low-level functions, which makes this specific task a lot easier. You can also create parameters like positioning, opacity, and several more. You can find them in the docs on &lt;a href=&quot;https://github.com/lukechilds/merge-images&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;use-cases-2&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;It’s a valuable library that can help with several tasks. For example, you can generate an NFT Collection where you can merge all components to have a complete set of variations. Or you can find this library helpful for personal use, for example, combining a few different images to generate a collage.&lt;/p&gt;
&lt;h3 id=&quot;example-2&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Install the library itself:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm install &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt;save merge&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;images&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you can use this code to generate a simple image:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//write this inside of your javascript file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; mergeImages &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;merge-images&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mergeImages&lt;/span&gt;&lt;span&gt;([&lt;/span&gt;&lt;span&gt;&apos;/body.png&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;/eyes.png&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;/mouth.png&apos;&lt;/span&gt;&lt;span&gt;]).&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  (&lt;/span&gt;&lt;span&gt;b64&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; (document.&lt;/span&gt;&lt;span&gt;querySelector&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;img&apos;&lt;/span&gt;&lt;span&gt;).src &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; b64)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//And that would update the img element to show this image:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I used it to merge several components to create a final variation (here I used Background, Character, Horns, Emotion, and Accessories).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Merge components for a new variation. I have used Background, Character, Horns, Emotion, and Accessories.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 4000px) 4000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;4000&quot; height=&quot;5000&quot; src=&quot;https://img.ly/_astro/Cark--0454--1-_ZtQqaO.webp&quot; srcset=&quot;/_astro/Cark--0454--1-_iiCUQ.webp 640w, /_astro/Cark--0454--1-_Z4eEGA.webp 750w, /_astro/Cark--0454--1-_1JCKo3.webp 828w, /_astro/Cark--0454--1-_19SXG5.webp 1080w, /_astro/Cark--0454--1-_1esn2E.webp 1280w, /_astro/Cark--0454--1-_Z22yC93.webp 1668w, /_astro/Cark--0454--1-_2ab9uD.webp 2048w, /_astro/Cark--0454--1-_Z1QdBGV.webp 2560w, /_astro/Cark--0454--1-_ZtQqaO.webp 4000w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;lookssame&quot;&gt;LooksSame&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/looks-same&quot;&gt;LooksSame&lt;/a&gt; is a library for comparing images. If the two images you uploaded are duplicates, the library will let you know. All you have to do is provide a link to the pictures you would like compared. LooksSame is not strictly an image manipulation library, but is helpful for testing purposes.&lt;/p&gt;
&lt;h3 id=&quot;use-cases-3&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;You can use this library and write code for automation and loop cycles that search a directory and compare each pair of your images for duplicates. Additionally, you can delete these duplicates and automate this process as well. It is a splendid library if you’re constantly working with ML algorithms that include large numbers of images.&lt;/p&gt;
&lt;h3 id=&quot;example-3&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;To start comparing images, you need just to install it by using this command:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span&gt; looks-same&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, you can see how to test this library with &lt;a href=&quot;https://jestjs.io/docs/getting-started&quot;&gt;Jest&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; looksSame &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;looks-same&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Parameters can be paths to files or buffer with compressed png image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;image1 and image2 are the same&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; () &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;looksSame&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;image1.png&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;image2.png&apos;&lt;/span&gt;&lt;span&gt;)).&lt;/span&gt;&lt;span&gt;toBe&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Result will be &quot;image1 and image2 are the same&quot; if they are the same&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;jimp&quot;&gt;Jimp&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jimp-dev/jimp&quot;&gt;Jimp&lt;/a&gt; stands for JavaScript Image Manipulation Program, that allows you to edit your image in almost every possible way. With it, you can invert your image, add some text, resize, use pixelation, clone images, blur them, invert colors, and several other cool features which will increase the image manipulation capabilities of your app.&lt;/p&gt;
&lt;h3 id=&quot;use-cases-4&quot;&gt;Use cases&lt;/h3&gt;
&lt;p&gt;With &lt;a href=&quot;https://github.com/jimp-dev/jimp&quot;&gt;Jimp&lt;/a&gt;, you can build your web application where you’ll be able to edit and manipulate images in almost any possible way. Crop, resize, rotate, and filter features let you create your own photo editor and add an interface on top of it. To streamline this process, you can try &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;&lt;strong&gt;PhotoEditor SDK&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(PE.SDK)&lt;/strong&gt;. PE.SDK will provide you with a polished user interface and photo editing features, so you can focus on the application you are building instead.&lt;/p&gt;
&lt;h3 id=&quot;example-4&quot;&gt;Example&lt;/h3&gt;
&lt;p&gt;Here’s the JavaScript code to try this excellent library. There’s an async function in which you can see many types of properties that you can easily change. Such as &lt;em&gt;Add Text&lt;/em&gt;, &lt;em&gt;Resize Image&lt;/em&gt;, &lt;em&gt;Blur the Image&lt;/em&gt;, etc. To use at least one of them, you’ll need to uncomment only part that you need, and your program is ready to run!&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;jsx&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// Import dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; Jimp&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; require&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;jimp&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; function&lt;/span&gt;&lt;span&gt; () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // Read the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  const&lt;/span&gt;&lt;span&gt; image&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; await&lt;/span&gt;&lt;span&gt; Jimp.&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;images/shapes.png&apos;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// &amp;#x3C;http://www.example.com/path/to/lenna.jpg&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // // Add text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  const font = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE); // bitmap fonts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.print(font, 0, 0, &apos;Hello world!&apos;); // &amp;#x3C;https://github.com/libgdx/libgdx/wiki/Hiero&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Resize the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Resize the image to 250 x 250&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.resize(250, 250);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Resize the height to 250 and scale the width accordingly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.resize(Jimp.AUTO, 250);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Resize the width to 250 and scale the height accordingly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.resize(250, Jimp.AUTO);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Add a sepia wash to the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.sepia();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Pixelation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.pixelate(5);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.pixelate(5, 50, 50, 190, 200); pixe,x, y, w, h&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Clone&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  const image2 = image.clone();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Blur the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.gaussian(1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.blur(1);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Inverts the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.invert();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Set the brightness&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.brightness( 0.5 ); // -1 to +1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Resize the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.resize(256, 256);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Set the quality&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.quality(100);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  // Convert to grayscale&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //  image.greyscale();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // Save the image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  image.&lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;images/edited-shapes.png&apos;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;// writeAsync&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;})();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;PS: Don’t forget to uncomment the effects which you want to use and save the file after. :)&lt;/p&gt;
&lt;p&gt;As you can see here, I blurred everything and inverted the colors for the previous image that I showed you, getting the following result:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2000px) 2000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2000&quot; height=&quot;2500&quot; src=&quot;https://img.ly/_astro/edited-shapes--1-_ZYNNbY.webp&quot; srcset=&quot;/_astro/edited-shapes--1-_Z1zlAHs.webp 640w, /_astro/edited-shapes--1-_rXLqj.webp 750w, /_astro/edited-shapes--1-_JK5t4.webp 828w, /_astro/edited-shapes--1-_ZfCEJE.webp 1080w, /_astro/edited-shapes--1-_Z1bDJEA.webp 1280w, /_astro/edited-shapes--1-_ZI62ME.webp 1668w, /_astro/edited-shapes--1-_ZYNNbY.webp 2000w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That’s it! Now you know the differences between five of the most popular image manipulation libraries for JavaScript. Some of them are useful for only one task, such as resizing images - others can do multiple tasks at once and help you with more processes. You have also met &lt;a href=&quot;https://img.ly/products/photo-sdk/&quot;&gt;PE.SDK&lt;/a&gt; to work smarter and save time building photo editing solutions, and focus on building your great product instead.&lt;/p&gt;</content:encoded><dc:creator>Mark</dc:creator><media:content url="https://blog.img.ly/2022/09/image-manipulation-libraries-javascript-1.png" medium="image"/><category>How-To</category><category>Image Manipulation</category><category>Image Editing</category><category>Insights</category></item><item><title>How to Stream Videos Using Javascript and HTML5</title><link>https://img.ly/blog/how-to-stream-videos-using-javascript-and-html5/</link><guid isPermaLink="true">https://img.ly/blog/how-to-stream-videos-using-javascript-and-html5/</guid><description>Learn how to stream videos right in your browser using only JavaScript and HTML5 APIs.</description><pubDate>Mon, 29 Aug 2022 20:36:00 GMT</pubDate><content:encoded>&lt;p&gt;If you would tell someone from the early 2000s what you’re about to do, they would be amazed and would give everything to understand how you did it. Because back then HTML was much simpler and didn’t even support video playback. So to stream your video inside of your browser you were forced to use some third-party services like Flash or Silverlight. Now we have HTML5 and new versions of JavaScript, and by combining these two new technologies you’ll end up with results that rival native applications. Streaming video inside of your web application nowadays is a breeze.&lt;/p&gt;
&lt;h2 id=&quot;the-video-tag&quot;&gt;The &lt;code&gt;&amp;#x3C;video&gt;&lt;/code&gt; tag&lt;/h2&gt;
&lt;p&gt;You can easily start streaming your own video by using only one tag in HTML5. I’m talking about the &lt;code&gt;&amp;#x3C;video&gt;&lt;/code&gt; tag. It embeds a fully-fledged media player in the document and similar to the &lt;code&gt;img&lt;/code&gt; tag accepts a path to the media we want to play inside the &lt;code&gt;src&lt;/code&gt; attribute as well as accepting parameters for &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In addition, there are video-specific properties such as whether the video should loop or autoplay and whether to display the default browser controls.&lt;/p&gt;
&lt;p&gt;To handle the case of browsers not supporting the &lt;code&gt;video&lt;/code&gt; tag you can provide fallback content inside the &lt;code&gt;&amp;#x3C;video&gt;&amp;#x3C;/video&gt;&lt;/code&gt; tags.&lt;/p&gt;
&lt;iframe src=&quot;https://codesandbox.io/embed/fast-rgb-03tbl5?fontsize=14&amp;#x26;hidenavigation=1&amp;#x26;theme=dark&quot; title=&quot;fast-rgb-03tbl5&quot; allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;combining-with-javascript&quot;&gt;Combining with JavaScript&lt;/h2&gt;
&lt;p&gt;You can also combine this simple video streaming in HTML with JavaScript and make it more professional and be able to control your streaming manually. When you get an element from the DOM of a &lt;code&gt;video&lt;/code&gt; tag, the object that you get exposes various methods and attributes which can be used for manipulating media content. Firstly, we need to access the DOM and declare an object which will be used for our manipulations. Now we can use &lt;code&gt;myVideo&lt;/code&gt; to programmatically pause, change the playback rate and current time of the video.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; myVideo&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;#video1&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//pause the video&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;myVideo.&lt;/span&gt;&lt;span&gt;pause&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Change the speed of playback&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;myVideo.playbackRate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 3.0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;//Change current time&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;myVideo.currentTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 4&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, most videos that we see on the web today such as YouTube, Twitch, or any other social media display much more complex behaviors than just changing playback speed or pausing the video. On YouTube, you can change the quality of your video, add subtitles, or even add features like autoplay if you have several other videos queued up and don’t want to switch it manually.&lt;/p&gt;
&lt;p&gt;All those services actually still use a video tag. But instead of streaming a video file through the “src” attribute inside of your tag, they use powerful tools such as &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API&quot;&gt;Media Source Extensions&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP&quot;&gt;other adaptive streaming API&lt;/a&gt; that will help stream your video more efficiently.&lt;/p&gt;
&lt;h2 id=&quot;what-are-media-source-extensions-mse&quot;&gt;What are Media Source Extensions (MSE)&lt;/h2&gt;
&lt;p&gt;Media Source Extensions is a W3C specification that allows JavaScript to send streams to media codecs within Web browsers that support HTML5 video and audio that most browsers implement today. In other words, it allows JavaScript to generate streams and facilitate a variety of use cases like adaptive streaming and time-shifting live streams. It’s quite an advanced solution if you want to make your video playback more customizable and professional. MSE gives us finer grained control over how much and how often content is fetched, and some control over memory usage details, such as when buffers are evicted.&lt;/p&gt;
&lt;p&gt;Wrap your resource via the Media Source Extensions API instead of dealing with the URL directly (We’ll talk more closely about it a little bit later).&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 2000px) 2000px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;2000&quot; height=&quot;709&quot; src=&quot;https://img.ly/_astro/MediaSource_fyAaQ.webp&quot; srcset=&quot;/_astro/MediaSource_Z23x9ON.webp 640w, /_astro/MediaSource_1myAEA.webp 750w, /_astro/MediaSource_pO5aO.webp 828w, /_astro/MediaSource_1MlG3T.webp 1080w, /_astro/MediaSource_1cjHTR.webp 1280w, /_astro/MediaSource_GJoDh.webp 1668w, /_astro/MediaSource_fyAaQ.webp 2000w&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;this-specification-was-designed-with-the-following-goals&quot;&gt;This specification was designed with the following goals:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Let JavaScript create a media stream regardless of how the media is fetched.&lt;/li&gt;
&lt;li&gt;Leverage the browser cache as much as possible.&lt;/li&gt;
&lt;li&gt;Provide requirements for byte stream format specifications.&lt;/li&gt;
&lt;li&gt;Minimize the need for media parsing in JavaScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I mentioned, we are still using HTML5 video tags, and even more surprising is that we’ll still use the “src” attribute. Only this time, instead of adding a link to the video, add a link to the MediaSource object.&lt;/p&gt;
&lt;p&gt;If you’re a little bit confused, then don’t worry, I’ll explain everything. To enable this type of use case, the W3C has defined a static method &lt;code&gt;URL.createObjectURL&lt;/code&gt;. You can use this API to create a URL that directly points to a JavaScript object created on the client, rather than actually pointing to an online resource.&lt;/p&gt;
&lt;p&gt;You can see how it works in this example:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; videoTag&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;my-video&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// creating the MediaSource, just with the &quot;new&quot; keyword, and the URL for it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; myMediaSource&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MediaSource&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; url&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createObjectURL&lt;/span&gt;&lt;span&gt;(myMediaSource);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// attaching the MediaSource to the video tag&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoTag.src &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; url;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that you have a MediaSource, what should you do? That’s not the only MSE specification. It also defines another concept, Source Buffers.&lt;/p&gt;
&lt;h2 id=&quot;source-buffers&quot;&gt;*&lt;strong&gt;*Source Buffers**&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The SourceBuffer interface &lt;strong&gt;represents a chunk of media to be passed into an HTMLMediaElement and played via a MediaSource object.&lt;/strong&gt; To put the video directly into the MediaSource for playback, you’ll need Source Buffers. MediaSource contains one or more instances of it. Each is associated with a content type, such as &lt;code&gt;Audio&lt;/code&gt;, &lt;code&gt;Video&lt;/code&gt;, or both of them at the same time. Source buffers are all associated with a single MediaSource and are used in JavaScript to add video data directly to HTML5 video tags. Separating video and audio allows managing them separately on the server. Doing so has several advantages such as control over your traffic and increasing performance. This is how it works:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// -- Create a MediaSource and attach it to the video (We already learned about that) --&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; videoTag&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; document.&lt;/span&gt;&lt;span&gt;getElementById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;my-video&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; myMediaSource&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MediaSource&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; url&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createObjectURL&lt;/span&gt;&lt;span&gt;(myMediaSource);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;videoTag.src &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; url;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// 1. add source buffers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; audioSourceBuffer&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; myMediaSource.&lt;/span&gt;&lt;span&gt;addSourceBuffer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;audio/mp4; codecs=&quot;mp4a.40.2&quot;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; videoSourceBuffer&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; myMediaSource.&lt;/span&gt;&lt;span&gt;addSourceBuffer&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  &apos;video/mp4; codecs=&quot;avc1.64001e&quot;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// 2. download and add our audio/video to the SourceBuffers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// for the audio SourceBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;http://server.com/audio.mp4&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // The data has to be a JavaScript ArrayBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;arrayBuffer&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;audioData&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    audioSourceBuffer.&lt;/span&gt;&lt;span&gt;appendBuffer&lt;/span&gt;&lt;span&gt;(audioData);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// the same for the video SourceBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;&amp;#x3C;http://server.com/video.mp4&gt;&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // The data has to be a JavaScript ArrayBuffer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;arrayBuffer&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;videoData&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    videoSourceBuffer.&lt;/span&gt;&lt;span&gt;appendBuffer&lt;/span&gt;&lt;span&gt;(videoData);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;adaptive-streaming&quot;&gt;*&lt;strong&gt;*Adaptive Streaming**&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Many video players have an “auto quality” feature that automatically selects quality based on network speed. If you have a slow internet connection then you’ll end up watching a video in the lowest resolution (probably 360p or even lower), on the other hand, if the connection is good then the video will be in the highest resolution (probably 1080p or even higher). It depends on how many options the specific video has. In addition, your hardware capability is also taken into account.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 1920px) 1920px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;1920&quot; height=&quot;929&quot; src=&quot;https://img.ly/_astro/StreamingVideo_Z283hMX.webp&quot; srcset=&quot;/_astro/StreamingVideo_ZR8DDM.webp 640w, /_astro/StreamingVideo_1MDLQg.webp 750w, /_astro/StreamingVideo_2m6JDQ.webp 828w, /_astro/StreamingVideo_20Qkbx.webp 1080w, /_astro/StreamingVideo_Z1U1FVk.webp 1280w, /_astro/StreamingVideo_Z1iNCGF.webp 1668w, /_astro/StreamingVideo_Z283hMX.webp 1920w&quot;&gt;&lt;/p&gt;
&lt;p&gt;On the server side, we create different segments for every quality we want to support. For example, we would put the following files on our server:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;./video/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ├── ./360p/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     ├── video_0.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     ├── video_1.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     └── video_2.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;	├── ./720p/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     ├── video_0.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     ├── video_1.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  |     └── video_2.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └── ./1080p/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ├── video_0.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        ├── video_1.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        └── video_2.mp4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The web player then automatically selects the correct video file to load when the network or CPU state changes. This is entirely done in JavaScript. For video segments, it could, for example, look as follows:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;javascript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * We first derive the desired quality from the bandwidth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * Then pass it to the pushVideoSegment()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * which fetches each segment with the desired quality in turn and returns a promise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;**/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; pushVideoSegment&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;nb&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;wantedQuality&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; const&lt;/span&gt;&lt;span&gt; url&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;&amp;#x3C;http://my-server/video/&gt;&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; wantedQuality &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/segment&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; nb &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;.mp4&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; fetch&lt;/span&gt;&lt;span&gt;(url)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; response.&lt;/span&gt;&lt;span&gt;arrayBuffer&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;arrayBuffer&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; videoSourceBuffer.&lt;/span&gt;&lt;span&gt;appendBuffer&lt;/span&gt;&lt;span&gt;(arrayBuffer);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * Translate an estimated bandwidth to the right audio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * quality as defined on server-side.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@param&lt;/span&gt;&lt;span&gt; {number}&lt;/span&gt;&lt;span&gt; bandwidth&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@returns&lt;/span&gt;&lt;span&gt; {string}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; fromBandwidthToQuality&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;bandwidth&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; return&lt;/span&gt;&lt;span&gt; bandwidth &lt;/span&gt;&lt;span&gt;&gt;&lt;/span&gt;&lt;span&gt; 320e3&lt;/span&gt;&lt;span&gt; ?&lt;/span&gt;&lt;span&gt; &quot;360p&quot;&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt; &quot;720p&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// first estimate the bandwidth. Most often, this is based on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;// the time it took to download the last segments&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; bandwidth&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; estimateBandwidth&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; quality&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; fromBandwidthToQuality&lt;/span&gt;&lt;span&gt;(bandwidth);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;pushVideoSegment&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, quality)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; pushVideoSegment&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, quality))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; .&lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;=&gt;&lt;/span&gt;&lt;span&gt; pushVideoSegment&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, quality));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations, you’ve learned multiple ways how to stream a video file into your browser. We have explored several tools that are helping you not just change some video parameters by using vanilla JS and HTML, and also Media Source Extensions (MSE) that are helping all developers around the world to build professional web players which you’re using yourself, such as YouTube, Twitch, TikTok and many others.&lt;/p&gt;
&lt;p&gt;If you want to give your users the ability to also edit videos within your mobile application check out our &lt;a href=&quot;https://img.ly/products/video-sdk/&quot;&gt;Video Editor SDK&lt;/a&gt; offering features such as trimming, transforms, video composition and more. It’s fully customizable to match the look and feel of your app and the most performant solution on the market.&lt;/p&gt;
&lt;p&gt;Looking for more video capabilities? Check out our solutions for &lt;a href=&quot;https://img.ly/use-cases/story-reels-short-video-creation/&quot;&gt;Short Video Creation&lt;/a&gt;, and &lt;a href=&quot;https://img.ly/products/video-sdk-mobile/&quot;&gt;Camera SDK&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;If you have questions, feedback or comments reach out to us on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Mark</dc:creator><media:content url="https://blog.img.ly/2022/08/stream-videos-using-Javascript-and-HTML5.png" medium="image"/><category>How-To</category><category>Tech</category><category>Video Editing</category><category>Videos</category><category>Tutorial</category></item></channel></rss>