📜 ⬆️ ⬇️

Convert video ... to SVG

It so happened that for centuries, the only cross-browser way to show animation in a browser without JS is animated gif. If he had a JPEG-based counterpart - and the Internet could have been completely different ... Modern alternatives, for example APNG , do not work everywhere and with just a small amount of compression, and the long-awaited <video> tag suffers from patents.

I want to share the results of my small academic experiment in converting video to SVG format (which then with luck can simply be shown through <img src = "">).

Academic - because the problems of cross-browser compatibility are far from being solved, and therefore, in its current form, this is hardly applicable anywhere.
SVG is not only vector graphics, but also 3 or even 4 meters of high-quality video ...

First result

Happy owners of Firefox could immediately see the video without departing from the checkout, but Chrome - when embedding the resulting svg-picture through <img src = ""> falls, because it had to be removed from the article.
')
But you can open the SVG in a separate window . IE requires opening in a new window, and using the built-in SVG JS (this option works in a separate window in all 3 browsers, but in the built-in via <img src = ""> the form does not work anywhere ...).

Size : this video in SVG format takes 2.3MB, after GZIP compression by a web server - 1.56MB (base64 presses to file size before encoding). In GIF format, the same video takes 24.1Mb. Thus, the gain in size is 15 times with a much better quality.

Approaches to implementation

foreignObject
SVG allows you to embed arbitrary HTML (and not only) code through foreignObject. With it, you can insert inside the SVG and video / flash-player tag, but it all works completely differently in different browsers. In FF, for example, video works, and flash does not show anything, but sound plays. In Chrome, on the contrary, flash works and video does not.

It seems that nothing will come of it ...

Built in via base64 jpeg
The inclusion of base64-encoded images inside css and svg files has been used for quite a long time:
<image id="frame0" width="480" height="201" xlink:href="data:image/jpeg;base64,/9j//gAPTGF2YzU0Lj[...]"></image> 

Let's try to use it. It remains only to find a way to show pictures in turn ...

SVG SMIL
SMIL (Synchronized Multimedia Integration Language) allows us to implement the desired animation of the many embedded frames in SVG:
 <svg version="1.1" baseProfile="tiny" id="svg-root" width="100%" height="100%" viewBox="0 0 480 360" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <image id='frame0' width="320" height="240" xlink:href="data:image/jpeg;base64,/9j//gAPTGF2YzU0Lj[...]" display='inline'> <set id="show1" attributeName="display" to="inline" begin="0s;show4.end" dur="1s" fill="freeze"/> <set id="hide1" attributeName="display" to="none" begin="show1.end" dur="0.01s" fill="freeze"/> </image> <image id='frame1' width="320" height="240" xlink:href="data:image/jpeg;base64,/9j//gAPTGF2YzU0Lj[...]" display='none'> <set id="show2" attributeName="display" to="inline" begin="show1.end" dur="1s" fill="freeze"/> <set id="hide2" attributeName="display" to="none" begin="show2.end" dur="0.01s" fill="freeze"/> </image> <image id='frame2' width="320" height="240" xlink:href="data:image/jpeg;base64,/9j//gAPTGF2YzU0Lj[...]" display='none'> <set id="show3" attributeName="display" to="inline" begin="show2.end" dur="1s" fill="freeze"/> <set id="hide3" attributeName="display" to="none" begin="show3.end" dur="0.01s" fill="freeze"/> </image> <image id='frame3' width="320" height="240" xlink:href="data:image/jpeg;base64,/9j//gAPTGF2YzU0Lj[...]" display='none'> <set id="show4" attributeName="display" to="inline" begin="show3.end" dur="1s" fill="freeze"/> <set id="hide4" attributeName="display" to="none" begin="show4.end" dur="0.01s" fill="freeze"/> </image> </svg> 

Obviously, this does not work in IE (neither 9 nor 10) - because It does not support SMIL . In Firefox / Chrome, this already works in a separate window, and in FireFox - even in the case of embedding via the img tag.

Built-in SVG JavaScript for IE
The very possibility of embedding JavaScript inside a picture jarred me a little.
Nevertheless, this possibility is:
 <svg> [....] <script type="text/ecmascript"><![CDATA[ var svgDoc; var desiredFramesPerSecond=12; var msPerFrame = 1000/desiredFramesPerSecond; var numFrames = 4; var frameCt=0; svgDoc = document.getElementsByTagName("svg")[0]; setTimeout("AnimateEm()",msPerFrame); function AnimateEm(){ if (frameCt==0) startTime = new Date(); setTimeout("AnimateEm()",msPerFrame); svgDoc.getElementById('frame'+frameCt.toString()).style.display='none'; frameCt=(frameCt+1)%numFrames; svgDoc.getElementById('frame'+frameCt.toString()).style.display='inline'; } ]]></script> </svg> 

When opening svg in a separate window, it works in all 3 browsers, but when embedded it does not work in any of the browsers. Perhaps JS specialists can fix this ...

We generate our SVG video
1. We tear apart the avi-file into images:
 ffmpeg -i "atari.avi" -r 12 -y -qscale 5 -vf scale=480:-1 -f image2 atari%%03d.jpg 

2. Generate svg
 php -q convert.php >convert.svg 

 <svg version="1.1" baseProfile="tiny" id="svg-root" width="100%" height="100%" viewBox="0 0 480 201" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <? $numFrames = 217; $FPS = 12; for($i=0;$i<=$numFrames-1;$i++) { ?> <image id="frame<?=$i?>" width="480" height="201" xlink:href="data:image/jpeg;base64,<?=base64_encode(file_get_contents("atari".str_pad(($i+1),3,"0",STR_PAD_LEFT).".jpg"))?>" display="<?=($i==0)?"inline":"none"?>"> <set id="show<?=$i?>" attributeName="display" to="inline" begin="<?=($i==0?"0s;":"")?>show<?=($i+$numFrames-1)%$numFrames?>.end" dur="<?=1/$FPS?>s" fill="freeze"/> <set id="hide<?=$i?>" attributeName="display" to="none" begin="show<?=$i?>.end" dur="0.01s" fill="freeze"/> </image> <? } ?> </svg> 

You can download test pictures and generation script here .

I hope that lighter minds of Habr will be able to improve cross-browser compatibility of svg-video, and we will be able to forget megabyte animated gifs like a bad dream of the 90s ...

Source: https://habr.com/ru/post/158197/


All Articles