Suche…


Bemerkungen

In diesem Thema werden die verschiedenen Medientypen und deren Verwendung mit der Leinwand in der 2D-Oberfläche behandelt.

Medientypen haben generische und formatspezifische Kategorien

Medientypen

  • Animationen
  • Videos
  • Bilder
  • HD-Bilder
  • Vektorbild
  • Animierte Bilder

Medienformate

  • Jpg / Jpeg
  • Png
  • Gif
  • SVG
  • M-JPEG
  • Webm
  • Webp

Bilder

Es gibt eine Vielzahl von Bildformaten, die von Browsern unterstützt werden, aber kein Browser unterstützt sie alle. Wenn Sie über bestimmte Bildformate verfügen, die Wiki-Browser verwenden möchten, bieten unterstützte Bildformate einen guten Überblick.

Die beste Unterstützung gilt für die 3 Hauptformate "jpeg", "png" und "gif", wobei alle gängigen Browser Unterstützung bieten.

JPEG

JPEG-Bilder eignen sich am besten für Fotos und Fotos wie Bilder. Sie eignen sich nicht gut für Diagramme, Diagramme und Texte. JPEG-Bilder unterstützen keine Transparenz.

Canvas kann JPEG-Bilder über canvas.toDataURL und canvas.toBlob und bietet eine Qualitätseinstellung. Da JPEG keine Transparenz unterstützt, werden transparente Pixel für das endgültige Ausgabe-JPG mit Schwarz gemischt. Das resultierende Bild ist keine perfekte Kopie der Leinwand.

JPEG bei Wikipedia

PNG

PNG-Bilder sind Bilder von höchster Qualität und können auch einen Alphakanal für transparente Pixel enthalten. Die Bilddaten sind komprimiert, erzeugen jedoch keine Artefakte wie JPG-Bilder.

Aufgrund der verlustfreien Komprimierung und der Unterstützung des Alphakanals werden PNGs für Spiele, Komponentenbilder, Diagramme, Diagramme und Text verwendet. Wenn Sie sie für Fotos und Fotos wie Bilder verwenden, kann ihre Dateigröße viel größer als bei JPEG sein. .

Das PNG-Format bietet auch Animationsunterstützung, obwohl die Browserunterstützung begrenzt ist und der Zugriff auf die Animation zur Verwendung auf der Zeichenfläche nur über Javascript-APIs und -Bibliotheken möglich ist

Die Leinwand kann zum Kodieren von PNG-Bildern über canvas.toDataURL und canvas.toBlob das Ausgabeformat ist jedoch auf komprimiertes canvas.toDataURL canvas.toBlob RGBA-Format beschränkt. Das PNG liefert eine pixelgenaue Kopie der Leinwand.

PNG bei Wikipedia

GIF

GIFs werden für kurze Animationen verwendet, können aber auch verwendet werden, um Diagramme, Diagramme und Bilder in hoher Qualität bereitzustellen. GIFs verfügen über eine sehr begrenzte Farbunterstützung mit maximal 256 Farben pro Bild. Mit der Bildverarbeitung von Cleatern können GIF-Bilder besonders in der Animation überraschend gute Ergebnisse erzielen. Gifs bieten auch Transparenz, obwohl dies auf Ein oder Aus beschränkt ist

Wie bei PNG sind GIF-Animationen nicht direkt für die Verwendung auf der Leinwand zugänglich. Sie benötigen eine Javascript-API oder -Bibliothek, um Zugriff zu erhalten. GIF kann nicht über die Leinwand gespeichert werden und erfordert dazu eine API oder Bibliothek.

GIF auf Wikipedia

Ein Bild laden und anzeigen

So laden Sie ein Bild und platzieren es auf der Leinwand

var image = new Image();  // see note on creating an image
image.src = "imageURL";
image.onload = function(){
    ctx.drawImage(this,0,0);
}

Bild erstellen

Es gibt verschiedene Möglichkeiten, ein Bild zu erstellen

  • new Image()
  • document.createElement("img")
  • <img src = 'imageUrl' id='myImage'> Als Teil des HTML document.getElementById('myImage') und mit document.getElementById('myImage') abgerufen.

Das Bild ist ein HTMLImageElement

Image.src-Eigenschaft

Die Image- src kann eine beliebige gültige Image-URL oder eine codierte dataURL sein. Weitere Informationen zu Bildformaten und zur Unterstützung finden Sie in den Anmerkungen zu diesem Thema.

  • image.src = "http://my.domain.com/images/myImage.jpg"
  • image.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=" *

* Die dataURL ist ein 1 x 1 Pixel Gif-Bild, das Schwarz enthält

Hinweise zum Laden und Fehler

Das Bild wird geladen, wenn die src -Eigenschaft festgelegt ist. Das Laden ist synchron, aber das onload Ereignis wird nicht aufgerufen, bis die Funktion oder der Code beendet / zurückgegeben wurde.

Wenn Sie ein Bild von der Seite erhalten (z. B. document.getElementById("myImage") ) und dessen src ist, wurde es möglicherweise nicht geladen. Sie können den Status des Bildes mit HTMLImageElement.complete überprüfen. HTMLImageElement.complete der HTMLImageElement.complete der HTMLImageElement.complete true . Dies bedeutet nicht, dass das Bild geladen wurde, sondern auch, dass das Bild geladen wurde

  • geladen
  • Es gab einen Fehler
  • Die src-Eigenschaft wurde nicht festgelegt und entspricht der leeren Zeichenfolge ""

Wenn das Bild aus einer unzuverlässigen Quelle stammt und möglicherweise aus verschiedenen Gründen nicht verfügbar ist, wird ein Fehlerereignis generiert. In diesem Fall befindet sich das Bild in einem fehlerhaften Zustand. Wenn Sie dann versuchen, es auf die Leinwand zu zeichnen, wird der folgende Fehler ausgegeben

Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.

Mit dem image.onerror = myImgErrorHandler können Sie geeignete Maßnahmen ergreifen, um Fehler zu vermeiden.

Zeichnen eines SVG-Bildes

Um ein Vektor-SVG-Bild zu zeichnen, unterscheidet sich die Operation nicht von einem Rasterbild:
Sie müssen zuerst Ihr SVG-Bild in ein HTMLImage-Element laden und dann die drawImage() -Methode verwenden.

var image = new Image();
image.onload = function(){
    ctx.drawImage(this, 0,0);
}
image.src = "someFile.SVG";

SVG-Bilder haben gegenüber Rastern einige Vorteile, da Sie nicht an Qualität verlieren, unabhängig von der Skalierung, die Sie auf Ihre Leinwand zeichnen. Aber Vorsicht, es kann auch etwas langsamer sein, als ein Rasterbild zu zeichnen.

Für SVG-Bilder gelten jedoch mehr Einschränkungen als für Rasterbilder.

  • Aus Sicherheitsgründen kann kein externer Inhalt aus einem SVG-Bild geladen werden, auf das in einem HTMLImageElement verwiesen wird ( <img> ).
    Kein externes Stylesheet, kein externes Bild, auf das in SVGImage ( <image/> ) - Elementen verwiesen wird, kein externer Filter oder Element, das mit dem Attribut xlink:href ( <use xlink:href="anImage.SVG#anElement"/> ) oder dem funcIRI verknüpft ist ( url() ) Attributmethode usw.
    Außerdem haben im Hauptdokument angefügte Stylesheets keine Auswirkungen auf das SVG-Dokument, wenn es in einem HTMLImage-Element referenziert wird.
    Schließlich wird im SVG-Image kein Skript ausgeführt.
    Umgehung: Sie müssen alle externen Elemente in der SVG-Datei selbst anhängen, bevor Sie auf das HTMLImage-Element verweisen. (Für Bilder oder Schriftarten müssen Sie eine dataURI-Version Ihrer externen Ressourcen hinzufügen).

  • Für das Wurzelelement ( <svg> ) müssen die Attribute width und height auf einen absoluten Wert gesetzt sein.
    Wenn Sie die relative Länge (z. B. % ) verwenden, kann der Browser nicht wissen, um welche relative Länge es sich handelt. Einige Browser (Blink) versuchen, eine Vermutung zu treffen, aber die meisten ignorieren einfach Ihr Bild und zeichnen ohne Vorwarnung nichts.

  • Einige Browser färben die Leinwand, wenn ein SVG-Bild darauf gezeichnet wurde.
    Insbesondere Internet-Explorer <Edge auf jeden Fall und Safari 9, wenn ein <foreignObject> im SVG-Image vorhanden ist.

Grundlegendes Laden und Abspielen eines Videos auf der Leinwand.

Die Leinwand kann verwendet werden, um Videos aus verschiedenen Quellen anzuzeigen. In diesem Beispiel wird gezeigt, wie Sie ein Video als Dateiressource laden, anzeigen und einen einfachen Klick auf den Wiedergabe / Pause-Schalter auf dem Bildschirm hinzufügen.

Diese selbst beantwortete Frage zu stackoverflow Wie zeige ich ein Video mithilfe des HTML5- Zeichenbereichs an, so wird der folgende Beispielcode in Aktion gezeigt.

Nur ein Bild

Ein Video ist nur ein Bild, was die Leinwand angeht. Sie können es wie jedes Bild zeichnen. Der Unterschied besteht darin, dass das Video abgespielt werden kann und Ton hat.

Holen Sie sich Leinwand und Grundeinstellungen

// It is assumed you know how to add a canvas and correctly size it.
var canvas = document.getElementById("myCanvas"); // get the canvas from the page
var ctx = canvas.getContext("2d");
var videoContainer; // object to hold video and associated info

Video erstellen und laden

var video = document.createElement("video"); // create a video element
video.src = "urlOffVideo.webm"; 
// the video will now begin to load.
// As some additional info is needed we will place the video in a
// containing object for convenience
video.autoPlay = false; // ensure that the video does not auto play
video.loop = true; // set the video to loop.
videoContainer = {  // we will add properties as needed
     video : video,
     ready : false,   
};

Im Gegensatz zu Bildelementen müssen Videos nicht vollständig geladen werden, um auf der Leinwand angezeigt zu werden. Videos bieten auch eine Vielzahl zusätzlicher Ereignisse, mit denen der Status des Videos überwacht werden kann.

In diesem Fall möchten wir wissen, wann das Video abspielbereit ist. oncanplay bedeutet, dass genug Video geladen wurde, um etwas davon abzuspielen, aber es reicht nicht aus, um bis zum Ende abzuspielen.

video.oncanplay = readyToPlayVideo; // set the event to the play function that 
                                  // can be found below

Alternativ können Sie oncanplaythrough das oncanplaythrough wird, wenn genug Video geladen ist, damit es bis zum Ende abgespielt werden kann.

video.oncanplaythrough = readyToPlayVideo; // set the event to the play function that
                                         // can be found below

Verwenden Sie nur eines der canPlay-Ereignisse und nicht beide.

Das kann Ereignis abspielen (entspricht Image Onload)

function readyToPlayVideo(event){ // this is a referance to the video
    // the video may not match the canvas size so find a scale to fit
    videoContainer.scale = Math.min(
                         canvas.width / this.videoWidth, 
                         canvas.height / this.videoHeight); 
    videoContainer.ready = true;
    // the video can be played so hand it off to the display function
    requestAnimationFrame(undateCanvas);
}

Anzeige

Das Video wird nicht selbst auf der Leinwand abgespielt. Sie müssen es für jeden neuen Rahmen zeichnen. Da es schwierig ist, die genaue Bildrate zu kennen, und wenn sie auftreten, ist es am besten, das Video so anzuzeigen, als würde es mit 60 Bildern pro Sekunde laufen. Wenn die Bildrate niedriger ist, rendern wir dasselbe Bild nur zweimal. Wenn die Framerate höher ist, können die zusätzlichen Frames nicht angezeigt werden, so dass wir sie einfach ignorieren.

Das Videoelement ist nur ein Bildelement und kann wie jedes Bild gezeichnet werden. Sie können das Video skalieren, drehen, schwenken, spiegeln, einblenden, ausschneiden, nur Teile anzeigen und zweimal im zweiten zusammengesetzten Modus mit einem globalen Mischmodus zeichnen Effekte wie Aufhellen, Bildschirm usw. hinzufügen.

function updateCanvas(){
    ctx.clearRect(0,0,canvas.width,canvas.height); // Though not always needed 
                                                     // you may get bad pixels from 
                                                     // previous videos so clear to be
                                                     // safe
    // only draw if loaded and ready
    if(videoContainer !== undefined && videoContainer.ready){ 
        // find the top left of the video on the canvas
        var scale = videoContainer.scale;
        var vidH = videoContainer.video.videoHeight;
        var vidW = videoContainer.video.videoWidth;
        var top = canvas.height / 2 - (vidH /2 ) * scale;
        var left = canvas.width / 2 - (vidW /2 ) * scale;
        // now just draw the video the correct size
        ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
        if(videoContainer.video.paused){ // if not playing show the paused screen 
            drawPayIcon();
        }
    }
    // all done for display 
    // request the next frame in 1/60th of a second
    requestAnimationFrame(updateCanvas);
}

Grundlegende Steuerung der Wiedergabepause

Jetzt haben wir das Video geladen und angezeigt. Alles, was wir brauchen, ist die Wiedergabesteuerung. Wir werden es als Klick-Umschaltfunktion auf dem Bildschirm machen. Wenn das Video abgespielt wird und der Benutzer klickt, wird das Video angehalten. Bei Pause wird der Klick fortgesetzt. Wir werden eine Funktion hinzufügen, um das Video abzudunkeln und ein Wiedergabesymbol (Dreieck) zu zeichnen.

function drawPayIcon(){
     ctx.fillStyle = "black";  // darken display
     ctx.globalAlpha = 0.5;
     ctx.fillRect(0,0,canvas.width,canvas.height);
     ctx.fillStyle = "#DDD"; // colour of play icon
     ctx.globalAlpha = 0.75; // partly transparent
     ctx.beginPath(); // create the path for the icon
     var size = (canvas.height / 2) * 0.5;  // the size of the icon
     ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size);
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size);
     ctx.closePath();
     ctx.fill();
     ctx.globalAlpha = 1; // restore alpha
}    

Nun das Play-Pause-Event

function playPauseClick(){
     if(videoContainer !== undefined && videoContainer.ready){
          if(videoContainer.video.paused){                                 
                videoContainer.video.play();
          }else{
                videoContainer.video.pause();
          }
     }
}
// register the event
canvas.addEventListener("click",playPauseClick);

Zusammenfassung

Die Wiedergabe eines Videos ist sehr einfach über die Leinwand, das Hinzufügen von Effekten in Echtzeit ist ebenfalls einfach. Es gibt jedoch einige Einschränkungen bei den Formaten, wie Sie spielen und suchen können. MDN HTMLMediaElement ist der Ort, an dem die vollständige Referenz auf das Videoobjekt abgerufen wird.

Nachdem das Bild auf der Leinwand gezeichnet wurde, können Sie mit ctx.getImageData auf die darin enthaltenen Pixel zugreifen. Oder Sie können canvas.toDataURL um ein canvas.toDataURL zu schnappen und herunterzuladen. (Nur wenn das Video aus einer vertrauenswürdigen Quelle stammt und die Leinwand nicht verfälscht).

Beachten Sie, wenn das Video bei der Wiedergabe einen Ton hat, wird auch der Ton wiedergegeben.

Viel Spaß beim Video.

Erfassen Sie die Leinwand und speichern Sie sie als webM-Video

Erstellen eines WebM-Videos aus Leinwandrahmen und Wiedergabe als Leinwand oder Hochladen oder Herunterladen.

Beispiel Capture und Play Canvas

name = "CanvasCapture"; // Placed into the Mux and Write Application Name fields of the WebM header
quality = 0.7; // good quality 1 Best < 0.7 ok to poor
fps = 30; // I have tried all sorts of frame rates and all seem to work
          // Do some test to workout what your machine can handle as there
          // is a lot of variation between machines.
var video = new Groover.Video(fps,quality,name)
function capture(){
    if(video.timecode < 5000){ // 5 seconds
         setTimeout(capture,video.frameDelay);             
    }else{
         var videoElement = document.createElement("video");
         videoElement.src = URL.createObjectURL(video.toBlob());
         document.body.appendChild(videoElement);
         video = undefined; // DeReference as it is memory hungry.
         return;
    }
    // first frame sets the video size
    video.addFrame(canvas); // Add current canvas frame
}
capture(); // start capture

Anstatt große Anstrengungen zu unternehmen, nur um abgelehnt zu werden, ist dies eine schnelle Einfügung, um zu sehen, ob dies akzeptabel ist. Wird alle Details angeben, wenn akzeptiert. Zusätzliche Aufnahmeoptionen für bessere HD-Aufnahmeraten (von dieser Version entfernt, kann HD 1080 mit 50 Bildern pro Sekunde auf guten Computern aufnehmen.)

Dies wurde von Wammy inspiriert, ist jedoch eine vollständige Umschreibung mit der Kodierungsmethode, die den während der Aufnahme erforderlichen Speicherplatz erheblich reduziert. Kann mehr als 30 Sekunden bessere Daten erfassen und Algorithmen verarbeiten.

Hinweis Rahmen werden in webp Bilder codiert. Nur Chrome unterstützt die WebP-Zeichenkodierung. Für andere Browser (Firefox und Edge) müssen Sie einen Drittanbieter-WebP-Encoder wie Libwebp-Javascript verwenden. Das Codieren von WebP-Bildern über Javascript ist langsam. (wird die Unterstützung für unformatierte Webp-Bilder einschließen, wenn dies akzeptiert wird).

Der von Whammy inspirierte webM-Encoder : Ein Echtzeit-Javascript-WebM

var Groover = (function(){
    // ensure webp is supported 
    function canEncode(){
        var canvas = document.createElement("canvas");
        canvas.width = 8;
        canvas.height = 8;
        return canvas.toDataURL("image/webp",0.1).indexOf("image/webp") > -1;
    }
    if(!canEncode()){
        return undefined;
    }    
    var webmData = null;
    var clusterTimecode = 0;
    var clusterCounter = 0;
    var CLUSTER_MAX_DURATION = 30000;
    var frameNumber = 0;
    var width;
    var height;
    var frameDelay;
    var quality;
    var name;
    const videoMimeType = "video/webm"; // the only one.
    const frameMimeType = 'image/webp'; // can be no other
    const S = String.fromCharCode;
    const dataTypes = {
        object : function(data){ return toBlob(data);},
        number : function(data){ return stream.num(data);},
        string : function(data){ return stream.str(data);},
        array  : function(data){ return data;}, 
        double2Str : function(num){
            var c = new Uint8Array((new Float64Array([num])).buffer);
            return S(c[7]) + S(c[6]) + S(c[5]) + S(c[4]) + S(c[3]) + S(c[2]) + S(c[1]) + S(c[0]);
        }
    };    
   
    const stream = {
        num : function(num){ // writes int
            var parts = [];
            while(num > 0){ parts.push(num & 0xff); num = num >> 8; }
            return new Uint8Array(parts.reverse());
        },
        str : function(str){ // writes string
            var i, len, arr;
            len = str.length;
            arr = new Uint8Array(len);
            for(i = 0; i < len; i++){arr[i] = str.charCodeAt(i);}
            return arr;
        },
        compInt : function(num){ // could not find full details so bit of a guess
            if(num < 128){       // number is prefixed with a bit (1000 is on byte 0100 two, 0010 three and so on)
                num += 0x80;
                return new Uint8Array([num]);
            }else
            if(num < 0x4000){
                num += 0x4000;
                return new Uint8Array([num>>8, num])
            }else
            if(num < 0x200000){
                num += 0x200000;
                return new Uint8Array([num>>16, num>>8, num])
            }else
            if(num < 0x10000000){
                num += 0x10000000;
                return new Uint8Array([num>>24, num>>16, num>>8, num])
            }            
        }
    }
    const ids = { // header names and values
        videoData          : 0x1a45dfa3, 
        Version            : 0x4286,
        ReadVersion        : 0x42f7,
        MaxIDLength        : 0x42f2,
        MaxSizeLength      : 0x42f3,
        DocType            : 0x4282,
        DocTypeVersion     : 0x4287,
        DocTypeReadVersion : 0x4285,
        Segment            : 0x18538067,
        Info               : 0x1549a966,
        TimecodeScale      : 0x2ad7b1,
        MuxingApp          : 0x4d80,
        WritingApp         : 0x5741,
        Duration           : 0x4489,
        Tracks             : 0x1654ae6b,
        TrackEntry         : 0xae,
        TrackNumber        : 0xd7,
        TrackUID           : 0x63c5,
        FlagLacing         : 0x9c,
        Language           : 0x22b59c,
        CodecID            : 0x86,
        CodecName          : 0x258688,
        TrackType          : 0x83,
        Video              : 0xe0,
        PixelWidth         : 0xb0,
        PixelHeight        : 0xba,
        Cluster            : 0x1f43b675,
        Timecode           : 0xe7,
        Frame              : 0xa3,
        Keyframe           : 0x9d012a,
        FrameBlock         : 0x81,
    };
    const keyframeD64Header = '\x9d\x01\x2a'; //VP8 keyframe header 0x9d012a
    const videoDataPos = 1; // data pos of frame data header
    const defaultDelay = dataTypes.double2Str(1000/25);
    const header = [  // structure of webM header/chunks what ever they are called.
        ids.videoData,[
            ids.Version, 1,
            ids.ReadVersion, 1,
            ids.MaxIDLength, 4,
            ids.MaxSizeLength, 8,
            ids.DocType, 'webm',
            ids.DocTypeVersion, 2,
            ids.DocTypeReadVersion, 2
        ],
        ids.Segment, [
            ids.Info, [
                ids.TimecodeScale, 1000000,
                ids.MuxingApp, 'Groover',
                ids.WritingApp, 'Groover',
                ids.Duration, 0
            ],
            ids.Tracks,[
                ids.TrackEntry,[
                    ids.TrackNumber, 1,
                    ids.TrackUID, 1,
                    ids.FlagLacing, 0,     // always o
                    ids.Language, 'und',   // undefined I think this means
                    ids.CodecID, 'V_VP8',  // These I think must not change
                    ids.CodecName, 'VP8',  // These I think must not change
                    ids.TrackType, 1,
                    ids.Video, [
                        ids.PixelWidth, 0,
                        ids.PixelHeight, 0
                    ]
                ]
            ]
        ]
    ];    
    function getHeader(){
        header[3][2][3] = name;
        header[3][2][5] = name;
        header[3][2][7] =  dataTypes.double2Str(frameDelay);
        header[3][3][1][15][1] =  width;
        header[3][3][1][15][3] =  height;
        function create(dat){
            var i,kv,data;
            data = [];
            for(i = 0; i < dat.length; i += 2){
                kv = {i : dat[i]};
                if(Array.isArray(dat[i + 1])){
                    kv.d = create(dat[i + 1]);
                }else{
                    kv.d = dat[i + 1];
                }
                data.push(kv);
            }
            return data;
        }
        return create(header);
    }
    function addCluster(){
        webmData[videoDataPos].d.push({ i: ids.Cluster,d: [{ i: ids.Timecode, d: Math.round(clusterTimecode)}]}); // Fixed bug with Round
        clusterCounter = 0;
    }
    function addFrame(frame){
        var VP8, kfS,riff;
        riff = getWebPChunks(atob(frame.toDataURL(frameMimeType, quality).slice(23)));
        VP8 = riff.RIFF[0].WEBP[0];
        kfS = VP8.indexOf(keyframeD64Header) + 3;
        frame = {
            width: ((VP8.charCodeAt(kfS + 1) << 8) | VP8.charCodeAt(kfS)) & 0x3FFF,
            height: ((VP8.charCodeAt(kfS + 3) << 8) | VP8.charCodeAt(kfS + 2)) & 0x3FFF,
            data: VP8,
            riff: riff
        };
        if(clusterCounter > CLUSTER_MAX_DURATION){
            addCluster();            
        }
        webmData[videoDataPos].d[webmData[videoDataPos].d.length-1].d.push({
            i: ids.Frame, 
            d: S(ids.FrameBlock) + S( Math.round(clusterCounter) >> 8) +  S( Math.round(clusterCounter) & 0xff) + S(128) + frame.data.slice(4),
        });
        clusterCounter += frameDelay;        
        clusterTimecode += frameDelay;
        webmData[videoDataPos].d[0].d[3].d = dataTypes.double2Str(clusterTimecode);
    }
    function startEncoding(){
        frameNumber = clusterCounter = clusterTimecode = 0;
        webmData  = getHeader();
        addCluster();
    }    
    function toBlob(vidData){
        var data,i,vData, len;
        vData = [];
        for(i = 0; i < vidData.length; i++){
            data = dataTypes[typeof vidData[i].d](vidData[i].d);
            len  = data.size || data.byteLength || data.length;
            vData.push(stream.num(vidData[i].i));
            vData.push(stream.compInt(len));
            vData.push(data)
        }
        return new Blob(vData, {type: videoMimeType});
    }
    function getWebPChunks(str){
        var offset, chunks, id, len, data;
        offset = 0;
        chunks = {};
        while (offset < str.length) {
            id = str.substr(offset, 4);
            // value will have top bit on (bit 32) so not simply a bitwise operation
            // Warning little endian (Will not work on big endian systems)
            len = new Uint32Array(
                new Uint8Array([
                    str.charCodeAt(offset + 7),
                    str.charCodeAt(offset + 6),
                    str.charCodeAt(offset + 5),
                    str.charCodeAt(offset + 4)
                ]).buffer)[0];
            id = str.substr(offset, 4);
            chunks[id] = chunks[id] === undefined ? [] : chunks[id];
            if (id === 'RIFF' || id === 'LIST') {
                chunks[id].push(getWebPChunks(str.substr(offset + 8, len)));
                offset += 8 + len;
            } else if (id === 'WEBP') {
                chunks[id].push(str.substr(offset + 8));
                break;
            } else {
                chunks[id].push(str.substr(offset + 4));
                break;
            }
        }
        return chunks;
    }
    function Encoder(fps, _quality = 0.8, _name = "Groover"){ 
        this.fps = fps;
        this.quality = quality = _quality;
        this.frameDelay = frameDelay = 1000 / fps;
        this.frame = 0;
        this.width = width = null;
        this.timecode = 0;
        this.name = name = _name;
    }
    Encoder.prototype = {
        addFrame : function(frame){
            if('canvas' in frame){
                frame = frame.canvas;    
            }
            if(width === null){
                this.width = width = frame.width,
                this.height = height = frame.height
                startEncoding();
            }else
            if(width !== frame.width || height !== frame.height){
                throw RangeError("Frame size error. Frames must be the same size.");
            }            
            addFrame(frame);   
            this.frame += 1;
            this.timecode = clusterTimecode;
        },        
        toBlob : function(){
            return toBlob(webmData);
        }
    }
    return {
        Video: Encoder,
    }
})()


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow