Possible bug publishing from iOS 13+. Camera permission error.

Michael

New Member
Hello,

We are facing an issue to publish a WebRTC video in iOS, mainly in iOS 13.2 / 13.3. The code is working fine on other OS and browsers (including iOS 12). We are only having issues with iOS 13.2 / 13.3.

This error happens in 2 out of 10 attempts approximately, with more chances to happen if we try to broadcast two consecutive times without refreshing the browser page.

When the issue occurs, the broadcaster is not able to see its own camera, and the publish method throw an exception (The video never gets published).

We get the following error at console (thrown in Flashphoner.js on the line 12190 Web SDK - 0.5.28):
12:55:45 WARN core - NotReadableError: Failed starting capture of a video track

When we have that issue, even after closing entirely the Flashphoner session, the icon of the camera still shows in URL bar. It's like the camera is never released from the browser tab.

We can only solve the issue by 1) Refreshing the page or 2) Closing and reopening the browser if the first 1 does not solve the issue.

Options passed to Flashphoner.createSession method:

{"urlServer":"wss://URL-OF-OUR-SERVEr:8443","custom":{"server":"1"},"appKey":"chat"}

Options passed to session.createStream method:

{"name":"865bd7016b46e018e5b85e9f7288bee01f5c910e","display":{"jQuery18208311950920066109":192},"cacheLocalResources":false,"transport":"TCP","custom":{"server":"1"},"disableConstraintsNormalization":false,"constraints":{"video":{"width":0,"height":0,"maxBitrate":1024,"frameRate":30,"facingMode":"user"},"audio":{"autoGainControl":false,"bitrate":64}}}

Our publish code is the following:

Flashphoner.getMediaAccess(constraints, container, null, false).then(function (disp) {
Flashphoner.createSession(connect_options).on(SESSION_STATUS.ESTABLISHED, function(session){
browser_check(container, function(){
session.createStream(stream_options).on(STREAM_STATUS.PUBLISHING, function(publish_stream){
console.log('STREAM_STATUS.PUBLISHING');
}).on(STREAM_STATUS.UNPUBLISHED, function(){
console.log('STREAM_STATUS.UNPUBLISHED');
}).on(self.STREAM_STATUS.FAILED, function(stream){
console.log('STREAM_STATUS.FAILED');
}).publish();
});
}).on(SESSION_STATUS.DISCONNECTED, function(){
console.log('SESSION_STATUS.DISCONNECTED');
}).on(SESSION_STATUS.FAILED, function(){
console.log('SESSION_STATUS.FAILED');
});
}).catch(function (error) {
console.error(error);
}); function browser_check(container, callback)
{
callback = typeof callback == 'function' ? callback : function(){};
var is_safari = jQuery("html").hasClass("ios") && jQuery("html").hasClass("safari") && Flashphoner.getMediaProviders()[0].toLowerCase() == 'webrtc';
if (Flashphoner.getMediaProviders()[0] === "WSPlayer")
{
Flashphoner.playFirstSound();
callback();
}
else if (is_safari || Flashphoner.getMediaProviders()[0] === "MSE")
{
Flashphoner.playFirstVideo(container, false, PRELOADER_URL).then(function () {
callback();
});
}
else
callback();
}

1. Do you have any idea of what the problem is?

2. Is there any way to access the peer connection stream object through your Web SDK?
(We suspect that if we have access to it, we could try to ensure all the Stream tracks are closed before attempts to request a new one. We think that in this particular iPhone version the tracks are not being closed by your SDK and subsequently requests to it cause the bug).

Thank you,
 

Max

Administrator
Staff member
Good day.
We checked your code sample with iOS 13.3. There are some issues in your code:
1. Flashphoner.getMediaAccess() functions should be called after Flashphoner.playFirstVideo() promise resolved successfully, but not before:
Code:
browser_check(container, function(){
    Flashphoner.getMediaAccess(constraints, container, null, false).then(function (disp) {
        session.createStream(stream_options).on(STREAM_STATUS.PUBLISHING, function(publish_stream){
        ...
        }).publish();
    }).catch(function (error) {
        console.error(error);
    });
});
2. For local video element, Flashphoner.playFirstVideo should be called with true value for second parameter:
Code:
Flashphoner.playFirstVideo(container, true, PRELOADER_URL).then(function () { ...
3. Your Safari detection method does not work properly in iOS 13.3 (returns always false), so playFirstVideo is never called. Please use Browser.isSafariWebRTC() function:
Code:
var is_safari = Browser.isSafariWebRTC();
So, your code should look like this
Code:
Flashphoner.createSession(connect_options).on(SESSION_STATUS.ESTABLISHED, function(session){
   console.log('SESSION_STATUS.CONNECTED');
   browser_check(container, function(){
       Flashphoner.getMediaAccess(constraints, container, null, false).then(function (disp) {
           session.createStream(stream_options).on(STREAM_STATUS.PUBLISHING, function(publish_stream){
               console.log('STREAM_STATUS.PUBLISHING');
           }).on(STREAM_STATUS.UNPUBLISHED, function(){
               console.log('STREAM_STATUS.UNPUBLISHED');
           }).on(self.STREAM_STATUS.FAILED, function(stream){
               console.log('STREAM_STATUS.FAILED');
           }).publish();
       }).catch(function (error) {
           console.error(error);
       });
   });
}).on(SESSION_STATUS.DISCONNECTED, function(){
   console.log('SESSION_STATUS.DISCONNECTED');
}).on(SESSION_STATUS.FAILED, function(){
   console.log('SESSION_STATUS.FAILED');
});

function browser_check(container, callback)
{
    callback = typeof callback == 'function' ? callback : function(){};
    var is_safari = Browser.isSafariWebRTC();
    console.log("is_safari " + is_safari);
    if (Flashphoner.getMediaProviders()[0] === "WSPlayer")
    {
        Flashphoner.playFirstSound();
        callback();
    }
    else if (is_safari || Flashphoner.getMediaProviders()[0] === "MSE")
    {
        console.log("before playFirstVideo");
        Flashphoner.playFirstVideo(container, true, PRELOADER_URL).then(function () {
            console.log("playFirstVideo resolved");
            callback();
        });
    }
    else
       callback();
}
and it works on iOS 13.3

PS: To format code samples, please use CODE tag in square brackets
 
Top