Ashish Garg
Ashish Garg

Reputation: 60

Twilio Remote video from Safari iPhone showing black-screen in Angular 5

iPhone safari version: 11.2.5

Chrome version: Checking for updates Version 80.0.3987.163 (Official Build) (64-bit)

The connection is a peer to peer.

If I can give you an overview it's like -

Video is coming on iPhone from mac safari, Chrome, window laptop
Video is coming on Android Phone from mac safari, Chrome, window laptop
Video is coming on mac safari, Chrome, window laptop from Android Phone

Video is NOT COMING on mac safari, Chrome, window laptop from iPhone

Please let me know if you can help. Thanks in advance.

Upvotes: 0

Views: 2196

Answers (3)

Ashish Garg
Ashish Garg

Reputation: 60

I solve this issue

createLocalVideoTrack({
      video: { width: 1280, height: 720 },
    }).then(track => {
      if (this.localVideo) {
        const element = track.attach();
        this.renderer.data.id = track.sid;
        this.renderer.setStyle(element, 'width', '25%');
        this.renderer.appendChild(this.localVideo.nativeElement, element);
        this.attachVideoClass();
      }
    });

Should be :

   this.roomObj.localParticipant.videoTracks.forEach(publication => {
      const element = publication.track.attach();
      this.renderer.data.id = publication.track.sid;
      this.renderer.setStyle(element, 'width', '25%');
      this.renderer.appendChild(this.localVideo.nativeElement, element);
    })

Upvotes: 3

Ashish Garg
Ashish Garg

Reputation: 60

Please check code:

import { Injectable, EventEmitter, ElementRef, Renderer2, RendererFactory2 } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs';
import { connect, createLocalTracks, createLocalVideoTrack } from 'twilio-video';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Http } from '@angular/http';
import { Router } from '@angular/router';
import { BaCustomPreLoader } from './baCustomPreloader.service';


@Injectable()
export class TwilioService {

  remoteVideo: ElementRef;
  localVideo: ElementRef;
  previewing: boolean;
  msgSubject = new BehaviorSubject("");
  roomObj: any;

  roomParticipants;

  private renderer: Renderer2;
  constructor(
    private http: Http,
    private router: Router,
    private rendererFactory: RendererFactory2,
    private baCustomPreLoader: BaCustomPreLoader) {
    this.renderer = rendererFactory.createRenderer(null, null);
  }

  getToken(username): Observable<any> {
    return this.http.post('/abc', { uid: 'ashish' });
  }

  microphone = true;

  mute() {
    this.roomObj.localParticipant.audioTracks.forEach(function (
      audioTrack
    ) {
      audioTrack.track.disable();
    });
    this.microphone = false;
  }


  unmute() {
    this.roomObj.localParticipant.audioTracks.forEach(function (
      audioTrack,
      key,
      map
    ) {
      audioTrack.track.enable();
    });
    this.microphone = true;
  }


  connectToRoom(accessToken: string, options): void {
    connect(accessToken, options).then(room => {
      this.roomObj = room;

      if (!this.previewing && options['video']) {
        this.startLocalVideo();
        this.previewing = true;
      }

      this.roomParticipants = room.participants;
      room.participants.forEach(participant => {
        this.attachParticipantTracks(participant);
      });

      room.on('participantDisconnected', (participant) => {
        this.detachParticipantTracks(participant);
      });

      room.on('participantConnected', (participant) => {
        this.roomParticipants = room.participants;
        this.attachParticipantTracks(participant);

        participant.on('trackAdded', track => {

          const element = track.attach();
          this.renderer.data.id = track.sid;
          this.renderer.setStyle(element, 'height', '100%');
          this.renderer.setStyle(element, 'max-width', '100%');
          this.renderer.appendChild(this.remoteVideo.nativeElement, element);
          this.attachVideoClass();
          this.baCustomPreLoader.hide();
        });
      });

      // When a Participant adds a Track, attach it to the DOM.
      room.on('trackAdded', (track, participant) => {
        this.attachTracks([track]);
      });

      // When a Participant removes a Track, detach it from the DOM.
      room.on('trackRemoved', (track, participant) => {
        this.detachTracks([track]);
      });

      room.once('disconnected', room => {
        room.localParticipant.tracks.forEach(track => {
          track.track.stop();
          const attachedElements = track.track.detach();
          attachedElements.forEach(element => element.remove());
          room.localParticipant.videoTracks.forEach(video => {
            const trackConst = [video][0].track;
            trackConst.stop();  // <- error

            trackConst.detach().forEach(element => element.remove());

            room.localParticipant.unpublishTrack(trackConst);
          });



          let element = this.remoteVideo.nativeElement;
          while (element.firstChild) {
            element.removeChild(element.firstChild);
          }
          let localElement = this.localVideo.nativeElement;
          while (localElement.firstChild) {
            localElement.removeChild(localElement.firstChild);
          }
          this.router.navigate(['thanks']);
          setTimeout(() => {
            window.location.reload();
          }, 1000)
        });

      });
    }, (error) => {
      alert(error.message);
    });
  }

  attachParticipantTracks(participant): void {
    participant.tracks.forEach(part => {
      this.trackPublished(part);
    });
  }

  trackPublished(publication) {
    if (publication.isSubscribed)
      this.attachTracks(publication.track);

    if (!publication.isSubscribed)
      publication.on('subscribed', track => {
        this.attachTracks(track);
      });
  }

  attachTracks(tracks) {

    const element = tracks.attach();
    this.renderer.data.id = tracks.sid;
    this.renderer.setStyle(element, 'height', '100%');
    this.renderer.setStyle(element, 'max-width', '100%');
    this.renderer.appendChild(this.remoteVideo.nativeElement, element);
    this.attachVideoClass();
    this.baCustomPreLoader.hide();
  }

  startLocalVideo(): void {
    createLocalVideoTrack({
      video: { width: 1280, height: 720 },
    }).then(track => {
      if (this.localVideo) {
        const element = track.attach();
        this.renderer.data.id = track.sid;
        this.renderer.setStyle(element, 'width', '25%');
        this.renderer.appendChild(this.localVideo.nativeElement, element);
        this.attachVideoClass();
      }
    });
  }

  detachParticipantTracks(participant) {
    this.detachTracks(participant);
  }

  detachTracks(tracks): void {
    tracks.tracks.forEach(track => {
      let element = this.remoteVideo.nativeElement;
      while (element.firstChild) {
        element.removeChild(element.firstChild);
      }
    });
  }

  attachVideoClass() {
    let remote = document.getElementById('remote');
  }
}

Upvotes: -1

philnash
philnash

Reputation: 73029

Twilio developer evangelist here.

I would recommend reading through the developing for Safari 11 article which goes over a bunch of potential issues.

Upvotes: 0

Related Questions