Videos recorded in Record RTC on Chrome do not play on Safari

562 Views Asked by At

I'm trying to record videos using the RecordRTC library but the issue is that videos recorded in Chrome Macbook do not play in

-Safari Macbook+iPhone -Chrome iPhone

This is the source code using the RecordRTC and the serie of testingsenter image description here


var startCameraBtn = document.querySelector('#start-camera-btn');
var startRecordingBtn = document.querySelector('#start-recording-btn');
var stopRecordingBtn = document.querySelector('#stop-recording-btn');
var retakeRecordingBtn = document.querySelector('#retake-recording-btn');
var saveRecordingBtn = document.querySelector('#save-recording-btn');
var publishJobBtn = document.querySelector('#publish-job-btn');
var video = document.querySelector('video');

var recorder; // globally accessible
var blob;
var mimeType;  // "video/webm;codecs=vp9";
var videoFormat; //webm

check_user_browser();

function captureCamera(callback) {
    navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function(camera) {
        callback(camera);
        console.log("Camera started");
    }).catch(function(error) {
        alert('Unable to capture your camera. Please check console logs.');
        console.error(error);
    });
}

function stopRecordingCallback() {
    video.src = video.srcObject = null;
    video.muted = false;
    video.volume = 1;
    blob = recorder.getBlob()
    video.src = URL.createObjectURL(blob);
    
    //recorder.camera.stop();
    //recorder.destroy();
    //recorder = null;
}



function startCamera(){
    this.style.display = "none";
    saveRecordingBtn.style.display = "none";
    startRecordingBtn.style.display = "block";
    
    captureCamera(function(camera) {
        video.muted = true;
        video.volume = 0;
        video.srcObject = camera;

        recorder = RecordRTC(camera, {
            type: 'video',

            // audio/webm
            // audio/webm;codecs=pcm
            // video/mp4
            // video/webm;codecs=vp9
            // video/webm;codecs=vp8
            // video/webm;codecs=h264
            // video/x-matroska;codecs=avc1
            // video/mpeg -- NOT supported by any browser, yet
            // audio/wav
            // audio/ogg  -- ONLY Firefox
            // demo: simple-demos/isTypeSupported.html
            mimeType: mimeType,

            // MediaStreamRecorder, StereoAudioRecorder, WebAssemblyRecorder
            // CanvasRecorder, GifRecorder, WhammyRecorder
            recorderType: MediaStreamRecorder,

            // disable logs
            disableLogs: true,

            // get intervals based blobs
            // value in milliseconds
            timeSlice: 1000,

            // requires timeSlice above
            // returns blob via callback function
            ondataavailable: function(blob) {},

            // auto stop recording if camera stops
            checkForInactiveTracks: false,

            // requires timeSlice above
            onTimeStamp: function(timestamp) {},

            // both for audio and video tracks
            bitsPerSecond: 128000,

            // only for audio track
            // ignored when codecs=pcm
            audioBitsPerSecond: 128000,

            // only for video track
            videoBitsPerSecond: 128000,

            // used by CanvasRecorder and WhammyRecorder
            // it is kind of a "frameRate"
            frameInterval: 90,

            // if you are recording multiple streams into single file
            // this helps you see what is being recorded
            previewStream: function(stream) {},

            // used by CanvasRecorder and WhammyRecorder
            // you can pass {width:640, height: 480} as well
            video: HTMLVideoElement,

            // used by CanvasRecorder and WhammyRecorder
            canvas: {
                width: 640,
                height: 480
            },

            // used by StereoAudioRecorder
            // the range 22050 to 96000.
            sampleRate: 96000,

            // used by StereoAudioRecorder
            // the range 22050 to 96000.
            // let us force 16khz recording:
            desiredSampRate: 16000,

            // used by StereoAudioRecorder
            // Legal values are (256, 512, 1024, 2048, 4096, 8192, 16384).
            bufferSize: 16384,

            // used by StereoAudioRecorder
            // 1 or 2
            numberOfAudioChannels: 2,

            // used by WebAssemblyRecorder
            frameRate: 30,

            // used by WebAssemblyRecorder
            bitrate: 128000,

            // used by MultiStreamRecorder - to access HTMLCanvasElement
            elementClass: 'multi-streams-mixer'

        });

      //  alert("video/webm;codecs=h264");

        // release camera on stopRecording
        recorder.camera = camera;
    });
}
function startRecording(){
    this.style.display = "none";
    stopRecordingBtn.style.display = "block";
    recorder.startRecording();
}
function stopRecording(){
    this.style.display = "none";
    retakeRecordingBtn.style.display = "block";
    saveRecordingBtn.style.display = "block";
    recorder.stopRecording(stopRecordingCallback);
}
function saveRecording(){
    this.innerHTML = 'Saving...';
     // generating a random file name
    var fileName = getFileName(videoFormat);

    // we need to upload "File" --- not "Blob"
    var fileObject = new File([blob], fileName, {
         type: 'video/'.videoFormat
    });
    uploadToPHPServer(fileObject, function(response, fileDownloadURL) {
        console.log(response);
    });
}
startCameraBtn.onclick = startCamera;
startRecordingBtn.onclick = startRecording;
stopRecordingBtn.onclick = stopRecording;
retakeRecordingBtn.onclick = startCamera;
saveRecordingBtn.onclick = saveRecording;


function uploadToPHPServer(blob, callback) {
    // create FormData
    var formData = new FormData();
    formData.append('video-filename', blob.name);
    formData.append('video-blob', blob);
    callback('Uploading recorded-file to server.');

    var upload_url = 'upload_video.php';
    // var upload_url = 'RecordRTC-to-PHP/save.php';

    var upload_directory = upload_url;
    // var upload_directory = 'RecordRTC-to-PHP/uploads/';
                
    makeXMLHttpRequest(upload_url, formData, function(progress) {
        if (progress !== 'upload-ended') {
            callback(progress);
            return;
        }
        var initialURL = upload_directory + blob.name;
        callback('ended', initialURL);
    });
}

function makeXMLHttpRequest(url, data, callback) {
    var request = new XMLHttpRequest();
    request.onreadystatechange = function() {
        if (request.readyState == 4 && request.status == 200) {
            if (request.responseText === 'success') {
                callback('upload-ended');
                return;
            }
            saveRecordingBtn.innerHTML = request.responseText;
            publishJobBtn.style.display = "block";
            return;
        }
    };
    request.upload.onloadstart = function() {
        callback('PHP upload started...');
    };
    request.upload.onprogress = function(event) {
        callback('PHP upload Progress ' + Math.round(event.loaded / event.total * 100) + "%");
    };
    request.upload.onload = function() {
        callback('progress-about-to-end');
                };
    request.upload.onload = function() {
        callback('PHP upload ended. Getting file URL.');
    };
    request.upload.onerror = function(error) {
        callback('PHP upload failed.');
    };
    request.upload.onabort = function(error) {
        callback('PHP upload aborted.');
    };
    request.open('POST', url);
    request.send(data);
}

function check_user_browser(){
    if (navigator.userAgent.indexOf('Chrome') !== -1 ) {
        console.log("Chrome");
        mimeType="video/webm;codecs=vp9";
        videoFormat = "webm";
        console.log("Video format: "+videoFormat+" mimeType: "+mimeType);
    }else if(navigator.userAgent.indexOf('Safari') !== -1 ){
        console.log("Safari");
        mimeType="video/mp4;codecs=h264";
        videoFormat = "mp4";
        console.log("Video format: "+videoFormat+" mimeType: "+mimeType)
    }else if(navigator.userAgent.indexOf('Firefox') !== -1 ){
        console.log("Firefox");
        mimeType="video/webm;codecs=vp9";
        videoFormat = "webm";
        console.log("Video format: "+videoFormat+" mimeType: "+mimeType)
    }
}
// this function is used to generate random file name
            function getFileName(fileExtension) {
                var d = new Date();
                var year = d.getUTCFullYear();
                var month = d.getUTCMonth();
                var date = d.getUTCDate();
                return 'RecordRTC-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
            }

            function getRandomString() {
                if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
                    var a = window.crypto.getRandomValues(new Uint32Array(3)),
                        token = '';
                    for (var i = 0, l = a.length; i < l; i++) {
                        token += a[i].toString(36);
                    }
                    return token;
                } else {
                    return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
                }
            }

cross browser videos playing and recording

1

There are 1 best solutions below

2
jch On

Apple's support for WebM is sketchy, and I don't think that the limitations have been documented anywhere. My (possibly mistaken) understanding is that:

  • VP8 is reasonably well supported, but only for WebRTC tracks, not for playing WebM files;
  • VP9 is supported for WebRTC tracks on some versions of Safari only;
  • WebM is supported on desktop Safari, at least with VP8, perhaps also with VP9 on some versions of Safari;
  • iOS Safari does not support WebM at all, whatever the codec.

You therefore have the following solutions:

  • record as H.264, which is well-supported across a variety of devices, but might force you to pay a licencing fee;
  • record as WebM with the VP8 codec, and require your iOS users to install a third party video viewer (such as vlc);
  • continue recording as WebM with VP9, and declare that Safari is not supported due to Apple's hostile stance against patent-free codecs.