getusermedia зависает в мобильных браузерах

Приведенный ниже код JavaScript захватывает неподвижные изображения с веб-камеры на веб-сайте jQuery для мобильных устройств. Код отлично работает на настольных компьютерах, но на мобильных телефонах (Android и iOS) воспроизведение видео останавливается на первом кадре!

Код (извините за длину):

    window.shutter = document.createElement('audio');
    window.shutter.volume = 1;

    // var v = new uploadZone($('<img data-src="http://link-to-upload/" data-multiple="true"/>"));
    // v.load();
    uploadZone = function(element){
        var object = this,
            mobileInput = $('<input type="file" accept="image/*" multiple="multiple" />'),
            errBack = function(e){console.log('error',e);},
            localstream,
            canvas = document.createElement('canvas'),
            thumb = document.createElement('canvas'),
            ctx = canvas.getContext("2d"),
            ctxsmall = thumb.getContext("2d"),
            videoObj = {"video": true},
            video = document.createElement('video'),
            uz = $('<div id="uploadzone-container">'),
            snap = $('<a href="#" class="uz-snap"><i class="fa fa-camera"></i></a>'),
            confirm = $('<a href="#" class="uz-confirm"><i class="fa fa-check"></i></a>'),
            clear = $('<a href="#" class="uz-clear"><i class="fa fa-close"></i></a>'),
            collection = $('<form id="uploadzone-collection" class="scrollY"></form>'),
            backdrop = $('<div class="modal-backdrop fade in uploadZone"></div>'),
            choice = $('<div class="uz-choice"><h2>Upload picture</h2></div>'),
            webcam = $('<a class="btn btn-success">Webcam</a>'),
            files = $('<a class="btn btn-primary">Gallery</a>'),
            uzVid = $('<div id="uz-video-container"></div>'),
            upload = $('<a class="btn btn-warning" href="#"><i class="fa fa-upload"></i> upload </a>'),
            li = '<div><img width="80px" height="80px" src=""/><input name="title" type="text" /><input type="hidden"/> </div>';

        this.uploadObject = {
                img:[],//array of [title]=data
                cover: element.attr('data-cover'),//BOOL is this an album cover or not
                gallery: element.attr('data-snap-picture'), //album name
                date: element.attr('data-date') //when was this picture taken ?
            };
        canvas.width  = 600;
        canvas.height = 500;
        thumb.width  = 80;
        thumb.height = 80;
        if(element.is('[data-multiple]')){
            collection.append(upload.hide());
        }else{
            mobileInput.removeAttr('multiple');
        }
        //$.post(url, $('#uploadzone-collection').serialize()).done(function(o) {
        backdrop.click(function(){$(this).remove();uz.remove();object.stop()});
        webcam.click(function(e){object.webcamStart();});
        files.click(function(e){
            mobileInput.trigger('click');
            uz.append(collection);
        });
        mobileInput.change(function(evt){
            console.log('changed');
          //  console.log(new FormData( this ));
            var files = evt.target.files; // FileList object

            // Loop through the FileList and render image files as thumbnails.
            for (var i = 0, f; f = files[i]; i++) {
                // Only process image files.
                if (!f.type.match('image.*')) {continue;}

                var reader = new FileReader();
                // Closure to capture the file information.
                reader.onload = (function(theFile) {
                    return function(e) {
                        if(element.is('[data-multiple]')){
                            var newLi = $(li);
                            upload.show();
                            collection.append(newLi);
                            var title = escape(theFile.name);
                            newLi.find('img')[0].src = e.target.result;
                            object.uploadObject['img'].push({'title':title,'data':e.target.result});
                        }else{
                            element[0].src = e.target.result;
                            backdrop.trigger('click');
                            object.uploadObject['img'].push({'title':element.attr('data-snap-picture'),'data':e.target.result});
                            object.uploadAll();
                        }
                    };
                })(f);

                // Read in the image file as a data URL.
                reader.readAsDataURL(f);
            }
            if(collection.find('img').length > 0)upload.show(); else upload.hide();
        });


        clear.click(function(){
            snap.show();
            confirm.hide();
            clear.hide();
            video.play();
        });
        snap.click(function(){
            window.shutter.play();video.pause();
            snap.hide();
            confirm.show();
            clear.show();
        });
        confirm.click(function(){
            if(element.is('[data-multiple]')){
                var newLi = $(li);
                upload.show();
                collection.append(newLi);
                var title = prompt("Picture title", "Paper "+newLi.index());
                if (title != null) {
                    ctxsmall.drawImage(video, 0, 0, 80, 80);
                    ctx.drawImage(video, 0, 0, 600, 500);
                    newLi.find('img')[0].src = thumb.toDataURL();
                    newLi.find('input').val(title);
                    object.uploadObject['img'].push({'title':title,'data':canvas.toDataURL()});
                    clear.trigger('click');
                }else{
                    newLi.remove();
                }
            }else{
                ctx.drawImage(video, 0, 0, 600, 500);
                var dataURL = canvas.toDataURL();
                $(element)[0].src = dataURL;
                object.uploadObject['img'].push({'title':element.attr('data-snap-picture'),'data':dataURL});
                object.uploadAll();
                backdrop.trigger('click');
            }
        });
        upload.click(function(){
            object.uploadAll();
            backdrop.trigger('click');
        });

        this.uploadAll =function(){
            var url = element.attr('data-src')+'/'+element.attr('data-snap-picture');
            if(element.is('[data-cover]'))url= url+'/1';

            if(object.uploadObject['img'].length < 1)return console.log('nothing to upload');

            return $.post(url,object.uploadObject,function(){
                alert('success');
            }).fail(function(){alert('falied')}).then(function(){object.uploadObject['img']=[]});
        }
        this.load = function(){//with choice
            if(!$(element).is('[data-src]'))return alert('bad attempt');
            $('body').append(backdrop).append(uz.append(choice.append(webcam).append(files)));
        }
        this.stop = function(){
            if (video.mozSrcObject) {
                console.log('mox');
                video.mozSrcObject.stop();
                video.src = null;
            }else{
                video.src = "";
                if(localstream)localstream.stop();
            }
        };
        this.webcamStart = function(){
            choice.slideUp()
            object.start();
            uz.append(uzVid.append(video)).append(collection);
            uzVid.append(snap).append(confirm.hide());
        }
        this.start = function(){
            if (navigator.webkitGetUserMedia) {// WebKit-prefixed
                navigator.webkitGetUserMedia(videoObj, function(stream) {
                    video.src = window.webkitURL.createObjectURL(stream);
                    video.play();
                    localstream = stream;
                }, errBack);
            } else if (navigator.mozGetUserMedia) {// Firefox-prefixed
                navigator.mozGetUserMedia(videoObj, function(stream) {
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                    localstream = stream;
                }, errBack);
            }else if (navigator.getUserMedia) {// Standard
                navigator.getUserMedia(videoObj, function(stream) {
                    video.src = stream;
                    video.play();
                    localstream = stream;
                }, errBack);
            }
        };
    };

Я не уверен, что проблема в моей this.start() функции? Или есть что-то еще, о чем я не знаю при работе с веб-камерой на мобильных устройствах?


person Zalaboza    schedule 20.11.2014    source источник
comment
у него непонятный заголовок вопроса, getusermedia, где он полностью посвящен проблеме с тегами видео.   -  person KumailR    schedule 21.10.2020


Ответы (3)


video.setAttribute('autoplay', '');
video.setAttribute('muted', '');
video.setAttribute('playsinline', '');

Я должен сделать это, чтобы он работал в Safari. Кроме того, Chrome iOS и Firefox iOS просто не имеют разрешения на использование камеры каким-либо образом. Решение исходит от https://medium.com/@leemartin/hello-webrtc-on-safari-11-e8bcb5335295

person Ethan Yanjia Li    schedule 24.01.2020
comment
Работает как шарм. - person Courier; 12.02.2020
comment
Это старый вопрос, но ответ решил мою проблему. У меня были autoplay и playsinline, но не хватало muted. Все 3 должны быть включены, иначе видео будет приостановлено после 1-го кадра. - person Sinisa; 19.06.2020

Не уверен, что вы уже нашли решение этой проблемы, но пытались ли вы обернуть свои функции video.play внутри функции onloadedmetadata? У меня была такая же проблема, и это устранило ошибку в моем приложении.

video.onloadedmetadata = function(e) {
    video.play();
};
person James Bradley    schedule 14.10.2016

добавить автовоспроизведение в тег видео

 <video id="video" #video width="100%" height="auto"   autoplay></video>

это немедленно воспроизведет ваше видео

person KofiYah    schedule 06.09.2017