WebRTC does not work in Angular 5 on iOS Safari

2019-04-11 12:27发布

问题:

I'm building an app with WebRTC and it's not working in Angular 5 on iOS Safari. I use native WebRTC API, no framework.

First without Angular

To prove my point Angular is the problem, I did a WebRTC test with plain html and javascript. So I had an index.html and a my-webrtc.js.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">    
  <title>WebRTC Test</title>
</head>
<body>
  <div>
    <video id="local-video" playsinline autoplay muted></video>
    <video id="remote-video" playsinline autoplay></video>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>  
  <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  <script src="js/my-webrtc.js"></script>
</body>
</html> 

I put those two files on a TSL/SSL secured webserver. On the same server I have a basic signaling server installed. In the my-webrtc.js there is everything: signaling, offer, answer, ice candidates and connecting the stream to the HTML elements.

For all the tests I used only the LAN just to make sure no STUN or TURN is needed.

Test results

Everything works fine in these tested situations:

  • Desktop/Chrome <-> Desktop/Chrome
  • Desktop/Chrome <-> Desktop/Firefox
  • Desktop/Chrome <-> Desktop/Safari
  • Desktop/Chrome <-> Android/Tab/Chrome
  • Desktop/Chrome <-> iPhone/Safari
  • Desktop/Chrome <-> iPad/Safari
  • Desktop/Safari <-> iPhone/Safari
  • Desktop/Safari <-> iPad/Safari
  • iPad/Safari <-> iPhone/Safari

Specifications of the devices:

Desktop/Chrome
- Macbook MacOS 10.12.6
- Chrome 64.0.3282.140

Desktop/Firefox
- Macbook MacOS 10.12.6
- Firefox 58.0.1

Desktop/Safari
- Macbook MacOS 10.12.6
- Safari 11.0.3

Android/Tab/Chrome
- Samsung Galaxy Tab3 8.0 inch (SM-T310)
- Android 4.4.2
- Chrome 64.0.3282.137

iPad/Safari
- iPad mini 2 (A1489)
- iOS 11.2.5
- Safari

iPhone/Safari
- iPhone 6 (A1586)
- iOS 11.2.5
- Safari

After that I did another test leaving the adapter-latest.js out of the index.html and then still all the above tested situations work fine.

Now I put everything in Angular

Now I make the next step. I use Angular CLI version 1.6.3 to create a new Angular test app:

ng new webrtc-angular-test

It generates a new Angular 5.2.3 app. For signaling I need to install socket.io:

npm install --save socket.io-client@2.0.4

For typings in typescript I add:

npm install --save @types/webrtc@0.0.22
npm install --save @types/socket.io-client@1.4.32

Then in app.component.html I put the same as the index.html:

<video id="local-video" playsinline autoplay muted></video>
<video id="remote-video" playsinline autoplay></video>

And in app.component.ts I paste everything from my-webrtc.js. I had to make some small modifications so the javascript works in typescript. I didn't import any adaptor yet.

Then building it:

ng build

And copy the content of the dist to the same TSL/SSL secured webserver where also the signaling server runs.

Test result

It works well in these cases:

  • Desktop/Chrome <-> Desktop/Chrome
  • Desktop/Chrome <-> Desktop/Safari
  • Desktop/Chrome <-> Android/Tab/Chrome
  • Desktop/Chrome <-> Desktop/Firefox

After giving permission on iOS localStream is visible. When the RTCPeerConnection is established the remoteStream is normal visible on iOS and almost at the same time the localStream freezes. No error messages in the console. On the Desktop side everything is normal. If two iOS devices are involved, on both side localStream freezes. This happens in these cases:

  • Desktop/Chrome <-> iPhone/Safari
  • Desktop/Chrome <-> iPad/Safari
  • Desktop/Safari <-> iPhone/Safari
  • Desktop/Safari <-> iPad/Safari
  • iPad/Safari <-> iPhone/Safari

Adding the Webrtc Adapter

Then I install the webrtc-adapter:

npm install --save webrtc-adapter@6.1.1

In app.component.ts I put a import 'webrtc-adapter';

But things get even worse !!

Test result

It works well in these cases:

  • Desktop/Chrome <-> Desktop/Chrome
  • Desktop/Chrome <-> Desktop/Safari
  • Desktop/Chrome <-> Android/Tab/Chrome
  • Desktop/Chrome <-> Desktop/Firefox

After giving permission on iOS localStream is visible. When the RTCPeerConnection is established the remoteStream is normal visible on iOS and almost at the same time the localStream freezes. No error messages in the console. On the Desktop side everything is normal. If two iOS devices are involved, on both side localStream freezes. This happens in these cases:

  • Desktop/Chrome <-> iPhone/Safari
  • Desktop/Chrome <-> iPad/Safari

LocalStream is visible on both sides, but remoteStream is not visible on both sides. The logging says peerConnection is created. Offer is send/received and answer is send/received. RemoteStream is added but not visible. No Ice Candidates are being send. RTC peer connection state is changed to 'checking'. There are no error messages. The same happens in the following cases:

  • Desktop/Safari <-> iPhone/Safari
  • Desktop/Safari <-> iPad/Safari
  • iPad/Safari <-> iPhone/Safari

My conclusion:

I have a working WebRTC environment, just plain html with javascript. Then I put this into Angular 5 with typescript and it's not working anymore on iOS Safari. This must be a problem with Angular 5, or typescript or a dependency like zone.js.

My questions:

Do you agree with my conclusion or do I overlook something?
Who knows what is the problem and knows a solution?

Help is greatly appreciated!!

回答1:

The problem that occurs after adding the webrtc-adapter is caused by zone.js and is solved by adding the following line in polyfills.ts (if using angular-cli)

// rtc peer connection patch
import 'zone.js/dist/webapis-rtc-peer-connection';
// getUserMedia patch
import 'zone.js/dist/zone-patch-user-media';

You should add this after import 'zone.js/dist/zone'; that's already in this file.

I dropped an issue on GitHub for the main problem on iOS where localStream freezes.