Home Reference Source

js/plugins/ts-ebml-plugin.js

/**
 * @file ts-ebml-plugin.js
 * @since 3.3.0
 */

import videojs from 'video.js';

const ConvertEngine = videojs.getComponent('ConvertEngine');

// see https://github.com/legokichi/ts-ebml/issues/25
import {Buffer} from 'buffer';
window.Buffer = Buffer;

import * as ebml from 'ts-ebml';

/**
 * Converter engine using the ts-ebml library.
 *
 * Used to inject metadata, like duration, into webm files.
 *
 * @class
 * @augments videojs.ConvertEngine
 */
class TsEBMLEngine extends ConvertEngine {
    /**
     * Inject metadata.
     *
     * @param {Blob} data - Recorded data that needs to be converted.
     */
    convert(data) {
        const decoder = new ebml.Decoder();
        const reader = new ebml.Reader();
        reader.logging = false;
        reader.drop_default_duration = false;

        // save timestamp
        const timestamp = new Date();
        timestamp.setTime(data.lastModified);

        // notify listeners
        this.player().trigger('startConvert');

        // load and convert blob
        this.loadBlob(data).then((buffer) => {
            // decode
            let elms = decoder.decode(buffer);

            // see https://github.com/legokichi/ts-ebml/issues/33#issuecomment-888800828
            const validEmlType = ['m', 'u', 'i', 'f', 's', '8', 'b', 'd'];
            elms = elms.filter((elm) => validEmlType.includes(elm.type));

            elms.forEach((elm) => {
                reader.read(elm);
            });
            reader.stop();

            // generate metadata
            let refinedMetadataBuf = ebml.tools.makeMetadataSeekable(
                reader.metadatas, reader.duration, reader.cues);
            let body = buffer.slice(reader.metadataSize);

            // create new blob
            let result = new Blob([refinedMetadataBuf, body],
                {type: data.type});

            // add existing file info
            this.addFileInfo(result, timestamp);

            // store result
            this.player().convertedData = result;

            // notify listeners
            this.player().trigger('finishConvert');
        });
    }
}

// expose plugin
videojs.TsEBMLEngine = TsEBMLEngine;

export default TsEBMLEngine;