A.F.N
A.F.N

Reputation: 196

MediaSource API using timestampOffset

i tried to use MediaSource API for a little player. this is my code and it work if i use timestampOffset but because video files are not exactly 30 sec (maybe 30 sec and 3 milisecond) there is a gap while playing. it seem using timestampOffset is not necessary so when i try to remove this line sourceBuffer.timestampOffset += settings.segment_time; player only show first part. what i missed?

;(function ($) {
    $.fn.player = function (options) {
        var settings = $.extend({
            mimeCodec: 'video/mp4; codecs="avc1.640015, mp4a.40.2',
            segment_time: 30,
            download_gap: 60,
            end_on_error: true,
            autoplay: true,
            played: false,
            controls: false,
        }, options);
        if (!('MediaSource' in window && MediaSource.isTypeSupported(settings.mimeCodec)))
            throw 'Unsupported MIME type or codec: ' + settings.mimeCodec;
    this.start = function () {
        this.each(function () {
            if (!settings.hasOwnProperty('segment_id'))
                throw 'Property segment_id is required.';
            var video = this;
            if (settings.controls)
                $(video).attr('controls', '');
            var sourceBuffer = null;
            var mediaSource = new MediaSource();
            var segment_id = settings.segment_id;
            video.src = URL.createObjectURL(mediaSource);
            mediaSource.addEventListener('sourceopen', function () {
                sourceBuffer = this.addSourceBuffer(settings.mimeCodec);
                sourceBuffer.addEventListener('updateend', function () {
                    sourceBuffer.timestampOffset += settings.segment_time;
                    console.log('updateend:');
                    if (!settings.played && video.paused && settings.autoplay) {
                        console.log('play:');
                        video.play();
                        settings.played = true;
                    }
                });
                reader()
            });

            function reader() {
                fetcher(video.currentTime);
                interval(video, setInterval(function () {
                    fetcher(video.currentTime);
                }, settings.segment_time * 1000 / 4))
            }


            function fetcher(currentTime) {
                if (sourceBuffer.timestampOffset - currentTime < settings.download_gap) {
                    if (!sourceBuffer.updating) {
                        console.log('nexting:');
                        fetch('/tv/segments/next/' + segment_id).then(function (response) {
                            return response.json();
                        }).then(function (data) {
                            if (data.status === 200) {
                                fetch(data.result.current.filename).then(function (response) {
                                    return response.arrayBuffer()
                                }).then(function (res) {
                                    segment_id = data.result.next.id;
                                    console.log('appending:');
                                    sourceBuffer.appendBuffer(res);
                                });
                            } else {
                                if (settings.end_on_error)
                                    mediaSource.endOfStream();
                            }
                        });
                    }
                }
            }
        });
    };

    function interval(obj, data) {
        if (data) {
            $(obj).data('interval', data);
        } else {
            return $(obj).data('interval');
        }
    }

    this.stop = function () {
        this.each(function () {
            clearInterval(interval(this));
        });
    };
    return this;
};
}(jQuery));

Upvotes: 0

Views: 492

Answers (0)

Related Questions