flutter-webrtc: GetUserMedia() does not work for Safari and IOS devices

Hi! I am currently developing an app using the flutter_webrtc package. It turns out that when I call WebRTC’s getUserMedia method for my Flutter web app as below, it does not prompt me to check for camera permission, and the whole app is just stuck. This situation happens with Mac Safari and both IOS Chrome and Safari.

var stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
_localStream = stream;
_localRenderer.srcObject = _localStream;
stream.getTracks().forEach((element) {
  _peerConnection!.addTrack(element, stream); 
});

This code is directly from the official flutter_webrtc sample: https://github.com/flutter-webrtc/flutter-webrtc/blob/main/example/lib/src/get_user_media_sample.dart. The version of my flutter_webrtc package is 0.9.47, the version for my Mac safari is 17.3, the version for my Dart SDK is 3.2.3, and the version for my Flutter is 3.16.5.

In addition, I’ve found out the following code snippet from the compiled Javascript file main.dart.js. It seems that Flutter calls a specific method called webkitGetUserMedia which seems to fit into Safari, but it just doesn’t work. Probably due to some restrictions by Apple?

A.zu.prototype = {
        WO(a, b, c) {
            var s = new A.ay($.ah, t.xN),
                r = new A.bF(s, t.Rt),
                q = A.ar(["audio", b, "video", c], t.N, t.z),
                p = !a.getUserMedia
            p.toString
            if (p)
                a.getUserMedia = a.getUserMedia || a.webkitGetUserMedia || a.mozGetUserMedia || a.msGetUserMedia
            this.a51(a, new A.W_([], []).li(q), new A.a86(r), new A.a87(r))
            return s
        },
        a51(a, b, c, d) {
            return a.getUserMedia(b, A.ji(c, 1), A.ji(d, 1))
        }
}

I greatly appreciate anyone who knows the solution to this problem so that getUserMedia can work for Flutter Web App for IOS devices.

About this issue

  • Original URL
  • State: open
  • Created 3 months ago
  • Reactions: 4
  • Comments: 17 (1 by maintainers)

Most upvoted comments

managed to fix this by adding the ‘mandatory’ object to ‘video’:

  var stream = await navigator.mediaDevices.getUserMedia({
        'video': {
          'facingMode': 'user',
          'mandatory': {
            'minWidth': '640',
            'minHeight': '480',
          },
        },
        'audio': kReleaseMode,
      });

i actually don’t understand the logic behind this, at least there should be a warning to notify that it’s required.

I think you need to call _localRenderer.srcObject = _localStream; in setState to notify flutter to update your widget.

setState((){
   _localRenderer.srcObject = _localStream;
});

I’m facing the same issue. Any solution?

For me, the issue is not with GetUserMedia(). I found out in the WebRTC console log of Safari that it requires Member RTCIceServer.urls, and hence changing ICE Server configuration keys in the Peer Connection Configuration from “url” to “urls” solve the issue in Safari. Namely,

final configuration = <String, dynamic>{
  "iceServers": [
    {
      "urls": "..",  // the key here should be "urls" not "url"
      "username": "...",
      "credential": "..."
    },
  ],
  'sdpSemantics': 'unified-plan',
};

_peerConnection = await createPeerConnection(configuration);

Now, GetUserMedia() works, and the browsers on both my iPhone and Mac work to request the camera and render the stream. However, the WebRTC connection still does not work for browsers, either Chrome or Safari, on my iPhone. The media stream track is connected, but no frames are sent from the iPhone to the other peer. I believe this is a problem with IOS, but I’m still working it out. Does anyone have a solution to this?

I’m facing the same issue. Any solution?