如何在 ionic 平台的 APIRTC 上静音和取消静音视频/音频?

Posted

技术标签:

【中文标题】如何在 ionic 平台的 APIRTC 上静音和取消静音视频/音频?【英文标题】:how to Mute and Unmute video/audio on APIRTC for ionic platform? 【发布时间】:2020-10-01 05:25:51 【问题描述】:

我已经在 Ionic 平台上实现了视频通话集成,我可以打电话,但我不能静音音频和视频流。为了获取本地流,我使用了 apiRTC.getLocalStreams() 但获取 getLocalStreams 不是一种方法。对于静音音频 我使用了 localStraem.muteAudio()、this.webRTCClient.toggleAudioMute(this.callId)。 这里也同样的错误静音音频不是一种方法。谁能帮我解决这个问题?

谢谢。

这是我的代码

declare var iosrtc;

declare var apiRTC;
declare var apiCC;

const STATE_WAIT = "wait";
const STATE_INCALL = "incall";

const LABEL_CALL = "Call";
const LABEL_HANGOUT = "Hangout";

const COLOR_CALL = "#5cb85c";
const COLOR_HANGOUT = "#d9534f";

@Component(
  selector: 'page-home',
  templateUrl: 'home.html'
);

export class HomePage 

  distantNumber: any;
  webRTCClient: any;
  infoLabel: any;
  buttonLabel: any;
  buttonColor: any;
  state: any;
  localStraem;
  callId;

  isMute;

  constructor(public navCtrl: NavController, public alertCtrl: AlertController, public platform: Platform, public nativeAudio: NativeAudio) 

    this.isMute = false;


    this.incomingCallHandler = this.incomingCallHandler.bind(this);

    this.userMediaErrorHandler = this.userMediaErrorHandler.bind(this);

    this.remoteStreamAddedHandler = this.remoteStreamAddedHandler.bind(this);

    this.hangupHandler = this.hangupHandler.bind(this);

    this.refreshVideoView = this.refreshVideoView.bind(this);

    this.sessionReadyHandler = this.sessionReadyHandler.bind(this);

    this.userMediaSuccessHandler = this.userMediaSuccessHandler.bind(this);


    apiRTC.init(
      onReady: this.sessionReadyHandler,
      apiKey: "My APIKey",



    );

    this.nativeAudio.preloadComplex('uniqueI1', 'assets/tone.mp3', 1, 1, 0).then((succ) => 
      console.log("suu..........", succ)
    , (err) => 
      console.log("err..........", err)
    );

    this.infoLabel = "Registration Ongoing...";
    this.buttonLabel = LABEL_CALL;
    this.buttonColor = COLOR_CALL;
    this.state = STATE_WAIT;
  

  /**
   * Call Action
   */
  pushCall(event) 
    console.log("Push, callState=" + this.state);
    if (this.distantNumber && this.state == STATE_WAIT) 
      setTimeout(this.refreshVideoView, 4000);
      this.webRTCClient.call(this.distantNumber);
     else if (this.state == STATE_INCALL) 
      this.state = STATE_WAIT;
      this.buttonColor = COLOR_CALL;
      this.buttonLabel = LABEL_CALL;
      this.webRTCClient.hangUp();
    
  

  sessionReadyHandler(e) 

    console.log("sessionReadyHandler");
    apiRTC.addEventListener("incomingCall", this.incomingCallHandler);
    apiRTC.addEventListener("userMediaError", this.userMediaErrorHandler);
    apiRTC.addEventListener("remoteStreamAdded", this.remoteStreamAddedHandler);
    apiRTC.addEventListener("userMediaSuccess", this.userMediaSuccessHandler);
    apiRTC.addEventListener("hangup", this.hangupHandler);
    this.webRTCClient = apiCC.session.createWebRTCClient();

    this.infoLabel = "Your local ID : " + apiCC.session.apiCCId;
    this.callId = apiCC.session.apiCCId;
    this.localStraem= this.webRTCClient.getLocalStreams()   // getting here error like getLocalStreams is not a method
    // this.localStraem= apiRTC.getLocalStreams()   // getting here also same error 
  

  refreshVideoView() 
    if (this.platform.is('ios')) 
      console.log("REFRESH");
      iosrtc.refreshVideos();
    
  

  incomingCallHandler(e) 
    console.log("incomingCallHandler");
    this.state = STATE_INCALL;
    this.buttonColor = COLOR_HANGOUT;
    this.buttonLabel = LABEL_HANGOUT;
    setTimeout(this.refreshVideoView, 2000);
  

  hangupHandler(e) 
    console.log("hangupHandler");
    this.state = STATE_WAIT;
    this.buttonColor = COLOR_CALL;
    this.buttonLabel = LABEL_CALL;
    this.initMediaElementState(e.detail.callId);
  
  ;
  userMediaSuccessHandler(e) 
    console.log("userMediaSuccessHandler", e);

    console.log('loca..........' + JSON.stringify(e.detail.stream))
    this.webRTCClient.addStreamInDiv(
      e.detail.stream,
      e.detail.callType,
      "mini",
      'miniElt-' + e.detail.callId,
       width: "200px", height: "200px" ,
      false

    );
  

  userMediaErrorHandler(e) 
  

  muteAudio() 
    this.localStraem.muteAudio();     // here mute audio not a method error
    console.log('cal......id............' + this.callId)
    // this.webRTCClient.toggleAudioMute(this.callId)  

    // this.localStraem.getAudioTracks()[0].stop();
    //   this.localStraem.getTracks().forEach((track) => 
    //     track.stop();
    // );
  

  unmuteAudio() 
    // this.localStraem.unmuteAudio();
    this.localStraem.getTracks().forEach((track) => 
      track.start();
    );
  



  remoteStreamAddedHandler(e) 
    console.log('mute..........' + this.isMute)

    console.log("remoteStreamAddedHandler", e);
    this.state = STATE_INCALL;
    this.buttonColor = COLOR_HANGOUT;
    this.buttonLabel = LABEL_HANGOUT;
    this.webRTCClient.addStreamInDiv(
      e.detail.stream,
      e.detail.callType,
      "remote",
      'remoteElt-' + e.detail.callId,
       width: "200px", height: "200px" ,
      this.isMute
    );
    setTimeout(this.refreshVideoView, 1000);
  

  initMediaElementState(callId) 
    this.webRTCClient.removeElementFromDiv('mini', 'miniElt-' + callId);
    this.webRTCClient.removeElementFromDiv('remote', 'remoteElt-' + callId);
  

【问题讨论】:

那么如果你 console.log(apiRTC) - 声明的 var 是定义的? 是的,我也可以连接视频通话,我的问题是静音选项。请参考这段代码,我已经从这里导入了代码 github.com/apizee/ApiRTC-ionic 【参考方案1】:

首先,我会确保声明的“apiRTC”变量不是未定义的,并且您知道如何导入它以使其已定义。

然后,确保首先执行 apiRTC 的 init 方法 - 将此代码块移动到您声明 apiRTC var 的位置:

declare var apiRTC;

apiRTC.init(
      onReady: this.sessionReadyHandler,
      apiKey: "My APIKey",
);

注意:目前在您的代码中,您尝试在 apiRTC 初始化之前使用它。

然后,我会将您的方法 sessionReadyHandler 拆分为在其中您实际上正在初始化 this.localStream(straem?)。

里面有我的 cmets 的代码是这样的:

declare var iosrtc;
declare var apiRTC;

apiRTC.init(
    onReady: this.sessionReadyHandler,
    apiKey: "My APIKey",
);

console.log(apiRTC) // should return defined here

declare var apiCC;

const STATE_WAIT = "wait";
const STATE_INCALL = "incall";

const LABEL_CALL = "Call";
const LABEL_HANGOUT = "Hangout";

const COLOR_CALL = "#5cb85c";
const COLOR_HANGOUT = "#d9534f";

@Component(
  selector: 'page-home',
  templateUrl: 'home.html'
) // get rid of ; here
export class HomePage 

  distantNumber; // no point using type 'any' here
  webRTCClient;
  infoLabel;
  buttonLabel;
  buttonColor;
  state;
  localStraem;
  callId;
  isMute;

  constructor(public navCtrl: NavController, public alertCtrl: AlertController, public platform: Platform, public nativeAudio: NativeAudio) 

    // initialize handlers inside ngOnInit hook and you do not need binding 'this' here:
    /* this.incomingCallHandler = this.incomingCallHandler.bind(this);
    this.userMediaErrorHandler = this.userMediaErrorHandler.bind(this);
    this.remoteStreamAddedHandler = this.remoteStreamAddedHandler.bind(this);
    this.hangupHandler = this.hangupHandler.bind(this);
    this.refreshVideoView = this.refreshVideoView.bind(this);
    this.sessionReadyHandler = this.sessionReadyHandler.bind(this);
    this.userMediaSuccessHandler = this.userMediaSuccessHandler.bind(this); */

  ;

  ngOnInit() 

    this.nativeAudio.preloadComplex('uniqueI1', 'assets/tone.mp3', 1, 1, 0).then((succ) => 
        console.log("suu..........", succ)
    , (err) => 
        console.log("err..........", err)
    );
    this.isMute = false;
    this.infoLabel = "Registration Ongoing...";
    this.buttonLabel = LABEL_CALL;
    this.buttonColor = COLOR_CALL;
    this.state = STATE_WAIT;

    // moved here from sessionReadyHandler:
    this.webRTCClient = apiCC.session.createWebRTCClient();
    this.infoLabel = "Your local ID : " + apiCC.session.apiCCId;
    this.callId = apiCC.session.apiCCId;
    this.localStraem= this.webRTCClient.getLocalStreams()   // should work now;
    // this.localStraem= apiRTC.getLocalStreams()   // same
    this.sessionReadyHandler() // init listeners, you also might want to remove listeners inside onDestroy hook
  ;

  /**
   * Call Action
   */
  pushCall(event) 
    console.log("Push, callState=" + this.state);
    if (this.distantNumber && this.state == STATE_WAIT) 
      setTimeout(this.refreshVideoView, 4000);
      this.webRTCClient.call(this.distantNumber);
     else if (this.state == STATE_INCALL) 
      this.state = STATE_WAIT;
      this.buttonColor = COLOR_CALL;
      this.buttonLabel = LABEL_CALL;
      this.webRTCClient.hangUp();
    
  

  sessionReadyHandler()  // event argument is not used here

    console.log("sessionReadyHandler");
    apiRTC.addEventListener("incomingCall", this.incomingCallHandler);
    apiRTC.addEventListener("userMediaError", this.userMediaErrorHandler);
    apiRTC.addEventListener("remoteStreamAdded", this.remoteStreamAddedHandler);
    apiRTC.addEventListener("userMediaSuccess", this.userMediaSuccessHandler);
    apiRTC.addEventListener("hangup", this.hangupHandler);

  

  refreshVideoView() 
    if (this.platform.is('ios')) 
      console.log("REFRESH");
      iosrtc.refreshVideos();
    
  

  incomingCallHandler(e) 
    console.log("incomingCallHandler");
    this.state = STATE_INCALL;
    this.buttonColor = COLOR_HANGOUT;
    this.buttonLabel = LABEL_HANGOUT;
    setTimeout(this.refreshVideoView, 2000);
  

  hangupHandler(e) 
    console.log("hangupHandler");
    this.state = STATE_WAIT;
    this.buttonColor = COLOR_CALL;
    this.buttonLabel = LABEL_CALL;
    this.initMediaElementState(e.detail.callId);
  
  ;
  userMediaSuccessHandler(e) 
    console.log("userMediaSuccessHandler", e);

    console.log('loca..........' + JSON.stringify(e.detail.stream))
    this.webRTCClient.addStreamInDiv(
      e.detail.stream,
      e.detail.callType,
      "mini",
      'miniElt-' + e.detail.callId,
       width: "200px", height: "200px" ,
      false

    );
  

  userMediaErrorHandler(e) 
  

  muteAudio() 
    this.localStraem.muteAudio();     // here mute audio not a method error
    console.log('cal......id............' + this.callId)
    // this.webRTCClient.toggleAudioMute(this.callId)  

    // this.localStraem.getAudioTracks()[0].stop();
    //   this.localStraem.getTracks().forEach((track) => 
    //     track.stop();
    // );
  

  unmuteAudio() 
    // this.localStraem.unmuteAudio();
    this.localStraem.getTracks().forEach((track) => 
      track.start();
    );
  



  remoteStreamAddedHandler(e) 
    console.log('mute..........' + this.isMute)

    console.log("remoteStreamAddedHandler", e);
    this.state = STATE_INCALL;
    this.buttonColor = COLOR_HANGOUT;
    this.buttonLabel = LABEL_HANGOUT;
    this.webRTCClient.addStreamInDiv(
      e.detail.stream,
      e.detail.callType,
      "remote",
      'remoteElt-' + e.detail.callId,
       width: "200px", height: "200px" ,
      this.isMute
    );
    setTimeout(this.refreshVideoView, 1000);
  

  initMediaElementState(callId) 
    this.webRTCClient.removeElementFromDiv('mini', 'miniElt-' + callId);
    this.webRTCClient.removeElementFromDiv('remote', 'remoteElt-' + callId);
  

还不确定您为什么尝试在构造函数中使用“bind(this)”。在构造函数中,“this”没有值。它是新对象(在您的情况下为 Homepage 类)的替代品。 'this' 的值将在创建新对象时成为新对象。

【讨论】:

对我来说一切正常,上面的代码除了 localstream 和静音选项。请通过这个链接,这样你会更清楚,然后回答我 FYI:github.com/apizee/ApiRTC-ionic 谢谢你 我尝试了您的代码,但无法正常工作。收到类似 TypeError 的错误:无法读取 null 的属性“createWebRTCClient”【参考方案2】:

得到了静音选项的答案,这里是代码 只需将 userMediaSuccessHandler 替换为上述代码中的 userMediaSuccessHandler 方法

userMediaSuccessHandler(e) 
    console.log("userMediaSuccessHandler", e);
    this.webRTCClient.addStreamInDiv(
      e.detail.stream,
      e.detail.callType,
      "mini",
      'miniElt-' + e.detail.callId,
       width: "128px", height: "96px" ,
      true
    );

    this.myStreemAudio = e.detail.stream;

  

  myStreemAudio;
  isMute = false;
  muteCall(val) 

  if (val == 0) 
      this.myStreemAudio.getAudioTracks()[0].enabled = false;
     else 
      this.myStreemAudio.getAudioTracks()[0].enabled = true;
    

    console.log('de.........' + val)
  


  muteVideo(val) 
    if (val == 0) 
      this.myStreemAudio.getVideoTracks()[0].enabled = false;
     else 
      this.myStreemAudio.getVideoTracks()[0].enabled = true;
    
  

【讨论】:

以上是关于如何在 ionic 平台的 APIRTC 上静音和取消静音视频/音频?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IONIC 3 物理设备上运行我的应用程序

如何使用 Ionic 4 检测平台

Ionic 项目上没有文件夹平台

在 ios 上使用 ionic/cordova 添加平台期间未安装的插件

如何在安卓手机上静音相机快门声音

如何在 ios 上静音传入的文本