collab-project / videojs-record

video.js plugin for recording audio/video/image files
https://collab-project.github.io/videojs-record
MIT License
1.38k stars 313 forks source link

Can't record video in Safari #181

Closed bennybee closed 5 years ago

bennybee commented 6 years ago

Safari 11 added getUserMedia Support in Sept 2017, more details here: https://webkit.org/blog/7763/a-closer-look-into-webrtc/

When looking at the demo page:

https://collab-project.github.io/videojs-record/examples/audio-video.html

I initialise the camera, click record and camera starts recording. I click stop and it stops recording but no playback button appears.

Plays back fine in Chrome on the same device.

Get following console error:

GetRecorderType is not a constructor (evaluating 'new Recorder (mediaStream, config) 

from RecordRTC.j:87

versions

videojs

videojs version : 6.2.8 videojs-record version : 2.0.0

browsers

Safari v11

OSes

Mac OS 10.12.6

thijstriemstra commented 6 years ago

Can you reproduce this with a recordrtc.js example? i think the bugs there (and the browser itself).

thijstriemstra commented 6 years ago

Opened https://github.com/muaz-khan/RecordRTC/issues/351

screen shot 2017-11-08 at 20 30 13
thijstriemstra commented 6 years ago

@bennybee a new version (5.4.5) of recordrtc was published a few days ago, have you tried that yet?

thijstriemstra commented 6 years ago

Getting TypeError: undefined is not an object (evaluating 'riff.RIFF[0]') with recordrtc 5.4.6...

Looks like 'riff' is https://en.wikipedia.org/wiki/Resource_Interchange_File_Format, a wrapper around WEBM in this case?

thijstriemstra commented 6 years ago

Basically Safari does not have MediaRecorder support yet, see https://caniuse.com/#feat=mediarecorder When that becomes available we can look at this again but till then it's audio-only.

thijstriemstra commented 6 years ago

Changed the ticket title to reflect that audio-only and image-only recording do work in Safari (tested with 11.0.3), it's video recording that doesn't (using recordrtc).

octavn commented 6 years ago

Basically Safari does not have MediaRecorder support yet

This bug report on bugs.webkit.org tracks the MediaRecorder implementation in WebKit and thus Safari.

I encourage everyone to show their interest and add a comment describing how a MediaRecorder implementation would help their project/development. Creating an account takes a second.

Also, WebKit is an open source project so one can also contribute code towards implementing the MediaRecorder API.

dirkk0 commented 6 years ago

good idea. done.

rbjarnason commented 6 years ago

With ever-growing mobile usage, we're at about 65% for our websites, Safari iOS support is really important for us and we'd be happy to spend some time to help if there could be some sort of a workaround either in videojs-record or RecordRTC.

Plan B is to use WebRTC recording on the server using Kurento but using videojs-record would be easier and we wouldn't have to worry about live bandwidth quality issues. Does anybody have any pointers in what direction to look for work-arounds?

I've been testing the audio-video.html example on iPhone 8 and it does not show the live video, if I click on the record button I go into a full screen live preview panel and when I click the X I go back to the browser and now I have a single static camera frame from what I just recorded. So an image has been captured.

I've then ran the same test on BrowserStack on an iPhone 10 with DevTools and captured the errors. They seem all to have to do with "play".

Here is the first one that happens after you have clicked on the camera icon and given system permissions to use the camera and microphone. image

Then I click the record button and get a fullscreen dialog: image

image

This last repeating error happens here on the video.play() line in RecordRTC.js:

image

Finally here is a screenshot from BrowserStack of the single frame that is captured:

image

Here is a similar ticket on RecordRTC https://github.com/muaz-khan/RecordRTC/issues/351

rbjarnason commented 6 years ago

Regarding those play errors, could it be that we're hitting auto-play policy issues? https://webkit.org/blog/7734/auto-play-policy-changes-for-macos/

thijstriemstra commented 6 years ago

@rbjarnason I unfortunately do not have access to an iphone to test. If you can send me a fairly recent one I'll surely be able to fix all outstanding iOS bugs.

rbjarnason commented 6 years ago

@thijstriemstra I wish we could! :) But we are a small nonprofit working on open source software largely volunteer based. We run citizen crowdsourcing & participatory budgeting platforms and are working on adding audio/video based ideas and debates to the platform.

I will dig around a bit and see if I can work out the iOS auto-play issue and if that is the problem at all. Also, as an open source project, we are sponsored with free testing at BrowserStack and I can add you there to look at this problem, real iOS phones hooked up to the Chrome console, if you want and have the time ;) Actually aside from iOS bugs you can probably get a free BrowserStack open source account for this project.

rbjarnason commented 6 years ago

Update: By adding muted and playsinline to the video element in the demos then videojs-record does not crash. After commenting out 3x video.play() in RecorderRTC.js the live preview works and I can see whammy frames being added when I record but I get no playback on iOS and in onRecordComplete() there is nothing coming into this.player.recordedData. I will continue to investigate...

rbjarnason commented 6 years ago

It looks like the problem has something to do with the whammy recorder, in this trace below the onStopRecording is at first getting empty recordedData back to videojs-recorder and then after Whammy.compile never completes, I guess there should be another callback at the point of webworker finishing.

image

May this has something to do with https://github.com/muaz-khan/RecordRTC/issues/380

rbjarnason commented 6 years ago

Final results on this for now. I managed to record frames using canvas but not assembling them on the client as Safari doesn't support webm, even if that would be possible with webworker then it would be slow on the client at 25 fps. Sending the frames over to the server for assembly is possible but png frames are very large even if you would send them as binaries with web sockets every second or so. I've now researched locally recording a WebRTC stream on Safari quite a bit and there seems not to be any practical solutions yet. Please if anybody has any suggestions please let me know.

In the meantime, I'm working on implementing a recording solution using Kurento where the video is recorded on the server side through a live WebRTC stream. I'm still considering if I should use this solution for all browsers or just for Safari.

thijstriemstra commented 6 years ago

Final results on this for now. I managed to record frames using canvas but not assembling them on the client as Safari doesn't support webm, even if that would be possible with webworker then it would be slow on the client at 25 fps

Thanks for all the valuable feedback. To summarize:

So Safari can not be supported right now.

thijstriemstra commented 5 years ago

Check the Browser support wiki page to check current browser compatibility with this plugin.

octavn commented 5 years ago

videojs-record relies on RecordRTC which relies mainly on the MediaRecorder object from the MediaStream Recorder API to record video.

Safari 11 and 12 do not support the MediaStream Recorder API.

There is a bug report filled thus if you want native video recording in Safari you can help by commenting on it and explaining your use case.

Recently the bug's status changed to "under consideration" so there is a slight chance we will see the feature in Safari 13 next year.

THEozmic commented 5 years ago

@rbjarnason I'm curious about what tool you're using to debug on mobile here:

image

rbjarnason commented 5 years ago

@THEozmic I was using BrowserStack and their tools.

Namaskar-1F64F commented 5 years ago

@rbjarnason did you end up figuring anything out with webrtc stream recording on safari?

taiphamhdweb commented 5 years ago

Hi @thijstriemstra, Can we use Record Video on Safari with latest version of Videojs Record? I just test on Safari 11.11 It's show error as bellow:

TypeError: s is not a constructor (evaluating 'new r(e,t)')
r — RecordRTC.js:83
startRecording — RecordRTC.js:1208
value — videojs.record.js:2321
value — videojs.record.js:3550
(anonymous function) — videojs.record.js:3519
r — video.es.js:2031
dispatcher — video.es.js:1846
Me — video.es.js:1984
dispatcher — video.es.js:1846
thijstriemstra commented 5 years ago

@taiphamhdweb nope, if it ever gets implemented in Safari, this ticket will be updated.

taiphamhdweb commented 5 years ago

Thanks you @thijstriemstra

voordev commented 5 years ago

Same issue, shame Apple does not give this priority. Then we would have an almost cross platform solution. Uploading prevents skipped frames and other issues with network connectivity.

thijstriemstra commented 5 years ago

Good news! They've started implementing it in Webkit (which Safari uses): https://trac.webkit.org/changeset/237106/webkit/ and https://trac.webkit.org/changeset/239145/webkit/

Also mentioned here: https://webkit.org/blog/8475/release-notes-for-safari-technology-preview-68/

thijstriemstra commented 5 years ago

Downloaded Safari Preview 73 and there it is:

screenshot 2019-01-10 at 14 46 25

Time to test..

voordev commented 5 years ago

That is awesome news !

[Error] VIDEOJS: – "ERROR:" – TypeError: GetRecorderType is not a constructor (evaluating 'new Recorder(mediaStream, config)') — RecordRTC.js:93
TypeError: GetRecorderType is not a constructor (evaluating 'new Recorder(mediaStream, config)') — RecordRTC.js:93
    (anonymous function) (video.min.js:12:1481)
    error (video.min.js:12:2368)
    dispatcher (video.min.js:12:10365)
    pe (video.min.js:12:11112)
    trigger (video.min.js:12:15153)
    (anonymous function) (video.min.js:12:193742)
    n (video.min.js:12:12359)
    n (video.min.js:12:12359)
    dispatcher (video.min.js:12:10341)

It gives the same error though, I just downloaded latest version and tried to record. When clicking the record button it timer starts to count but the recording itsel is not processed as-is.

thijstriemstra commented 5 years ago

@voordev recordrtc still needs to update some stuff, see https://github.com/muaz-khan/RecordRTC/issues/351, but I just succesfully recorded an mp4 using this script:

var constraints = { video: true };
var chunks = [];
var mediaRecorder;

var start = document.getElementById('start');
var stop = document.getElementById('stop');
var myVideo = document.getElementById('myVideo');

start.onclick = function() {
    navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {

        mediaRecorder = new MediaRecorder(stream);
        mediaRecorder.start();
        console.log(mediaRecorder.state);
        console.log("recorder started");

        start.style.background = "red";
        start.style.color = "black";

        mediaRecorder.onstop = function(e) {
            console.log("data available after MediaRecorder.stop() called.");

            var blob = new Blob(chunks, {'type' : 'video/mp4'});
            chunks = [];
            var videoURL = URL.createObjectURL(blob);
            myVideo.src = videoURL;
            console.log("recorder stopped");
        };

        mediaRecorder.ondataavailable = function(e) {
            chunks.push(e.data);
        };
    });
};

stop.onclick = function() {
    mediaRecorder.stop();
    console.log(mediaRecorder.state);
    console.log("recorder stopped");
    start.style.background = "";
    start.style.color = "";
};
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Safari test</title>

  <script src="../node_modules/webrtc-adapter/out/adapter.js"></script>

  <style>
  /* change player background color */
  #myVideo {
      background-color: #9FD6BA;
  }
  </style>

</head>
<body>

<video id="myVideo" controls autoplay playsinline></video>

<button id="start">Start</button>
<button id="stop">Stop</button>

<script src="safari.js"></script>

</body>
</html>

Video details:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/foo/Downloads/myClip.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 1
    compatible_brands: mp41mp42isom
    creation_time   : 2019-01-10T14:40:50.000000Z
  Duration: 00:00:04.86, start: 0.041667, bitrate: 3520 kb/s
    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 640x480 [SAR 1:1 DAR 4:3], 3547 kb/s, 18.26 fps, 600 tbr, 600 tbn, 1200 tbc (default)
    Metadata:
      creation_time   : 2019-01-10T14:40:50.000000Z
      handler_name    : Core Media Video
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
thijstriemstra commented 5 years ago

Safari 12 also doesn't support MediaRecorder unfortunately, we'll have to wait till v12 I guess. See #332

fabyeah commented 4 years ago

MediaRecorder hasn't landed in Safari 13 either. Any guesses when this will come? So at least not until Safari 14 in September, in another 9 months? 😢

octavn commented 4 years ago

A partial implementation of the MediaStream Recorder API was introduced 1 year ago in Safari Technology Preview 73 but never made it to production Safari.

https://blog.addpipe.com/safari-technology-preview-73-adds-limited-mediastream-recorder-api-support/

thijstriemstra commented 4 years ago

Safari team is either understaffed, incompetent or scared of shipping new features, I don't know. I do know it's a shit browser.

dankleying commented 4 years ago

Downloaded Safari Preview 73 and there it is:

screenshot 2019-01-10 at 14 46 25

Time to test..

Thanks for the reply. But in production how can we tell the users to allow this? Is there a way to enable MediaRecorder by code? Thank you in advance.

thijstriemstra commented 4 years ago

Is there a way to enable MediaRecorder by code?

No. If there was I would consider it a security issue in Safari.

dankleying commented 4 years ago

If there was I would consider it a security issue in Safari.

Just a follow-up. Since other browsers(Chrome, Firefox) allow recording, why is it an issue in Safari? Can you share some insights? Thank you.

thijstriemstra commented 4 years ago

No. If there was I would consider it a security issue in Safari.

I meant, enabling a Experimental Feature shouldn't be possible from JS.