html - Twilio 可编程视频在 ionic 4 中不可见
问题描述
我正在尝试使用 Twilio 视频实现视频通话,此处连接但提供 Twilio 访问令牌。
我获得了访问令牌,但本地房间(本地摄像头预览视频不可见),我正在尝试连接远程视频。远程视频也已连接,但未显示在移动屏幕上。
HTML
<ion-content #scrollArea fullscreen>
<div id="video-container">
<div id="local" #localVideo>
<p>local video</p>
</div>
<div id="remote" #remoteVideo>
<p>remote video</p>
</div>
<input type="text" [(ngModel)]="username" placeholder="username">
<input type="text" [(ngModel)]="roomName" placeholder="room name">
<input type="button" [disabled]="!username || !roomName ? true : false" value="connect" (click)="connect()">
<input type="button" [disabled]="!twilioService.roomObj ? true : false" value="disconnect" (click)="disconnect()">
</div>
</ion-content>
ts
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { TwiliovideoService } from '../_service/twiliovideo.service';
import { ServiceProxy, ServiceRegistry } from '../_helpers/ServiceProxy';
import { IonContent } from '@ionic/angular';
import { async } from '@angular/core/testing';
@Component({
selector: 'app-videocall',
templateUrl: './videocall.component.html',
styleUrls: ['./videocall.component.scss'],
})
export class VideocallComponent implements OnInit {
message1: string;
accessToken: string;
roomName: string;
username: string;
@ViewChild('scrollArea') content: IonContent;
@ViewChild('localVideo') localVideo: ElementRef;
@ViewChild('remoteVideo') remoteVideo: ElementRef;
video_token: any;
constructor(public twilioService: TwiliovideoService,public serviceProxy: ServiceProxy,) {
this.twilioService.msgSubject.subscribe(r => {
this.message1 = r;
});
}
ngOnInit() {
this.twilioService.localVideo = this.localVideo;
this.twilioService.remoteVideo = this.remoteVideo;
// this.connect();
}
//Video call
log(message) {
this.message1 = message;
}
disconnect() {
if (this.twilioService.roomObj && this.twilioService.roomObj !== null) {
this.twilioService.roomObj.disconnect();
this.twilioService.roomObj = null;
}
}
async connect() {
let date = Date.now();
let video_start = {
userName: this.username,
roomName: this.roomName
}
console.log(this.roomName)
await this.serviceProxy.SingleRequest(ServiceRegistry.VIDEOCALL_SESSION,video_start).subscribe(async arg=>{
this.video_token = arg.result
});
console.log(this.video_token)
// localStorage.setItem('video_token', JSON.stringify({
// video_token: this.video_token,
// created_at: date
// }));
// let storage = JSON.parse(localStorage.getItem('video_token') || '{}');
// if (!this.roomName || !this.username) { this.message1 = "enter username and room name."; return; }
// if (storage['video_token'] && storage['created_at'] + 3600000 > date) {
if(this.video_token){
this.accessToken = this.video_token
await this.twilioService.connectToRoom(this.accessToken, { name: this.roomName, audio: true, video: { width: 240 } })
// return;
}
// if (this.video_token!= null)
// this.twilioService.connectToRoom(this.accessToken, { name: this.roomName, audio: true, video: { width: 240 } })
}
//
}
服务.ts
import { Injectable, ElementRef } from '@angular/core';
import { connect, createLocalTracks, createLocalVideoTrack } from 'twilio-video';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class TwiliovideoService {
msgSubject = new BehaviorSubject("");
remoteVideo: ElementRef;
localVideo: ElementRef;
previewing: boolean;
roomObj: any;
constructor() { }
connectToRoom(accessToken: string, options): void {
connect(accessToken, options).then(room => {
console.log(`Successfully joined a Room: ${room}`);
if (!this.previewing && options['video']) {
this.startLocalVideo();
this.previewing = true;
}
// Attach the Participant's Media to a <div> element.
room.on('participantConnected', participant => {
console.log(`Participant "${participant.identity}" connected`);
participant.tracks.forEach(publication => {
if (publication.isSubscribed) {
const track = publication.track;
this.remoteVideo.nativeElement.appendChild(track.attach());
}
});
participant.on('trackSubscribed', track => {
this.remoteVideo.nativeElement.appendChild(track.attach());
});
});
// Log your Client's LocalParticipant in the Room
const localParticipant = room.localParticipant;
console.log(`Connected to the Room as LocalParticipant "${localParticipant.identity}"`);
// Log any Participants already connected to the Room
room.participants.forEach(participant => {
console.log(`Participant "${participant.identity}" is connected to the Room`);
participant.on('trackSubscribed', track => {
this.remoteVideo.nativeElement.appendChild(track.attach());
});
});
// Log new Participants as they connect to the Room
room.once('participantConnected', participant => {
console.log(`Participant "${participant.identity}" has connected to the Room`);
});
// Log Participants as they disconnect from the Room
room.once('participantDisconnected', participant => {
console.log(`Participant "${participant.identity}" has disconnected from the Room`);
});
}, error => {
console.error(`Unable to connect to Room: ${error.message}`);
});
}
startLocalVideo(): void {
createLocalVideoTrack().then(track => {
this.localVideo.nativeElement.appendChild(track.attach());
});
}
}
解决方案
您需要在 config.xml 和 AndroidManifest.xml 中授予音频和摄像头权限
安装 android 权限(遵循 ionic 文档)
在 config.xml 和 AndroidManifest.xml 中添加这些权限
<custom-config-file parent="/*" target="AndroidManifest.xml"> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera2.full" /> <uses-feature android:name="android.hardware.camera2.autofocus" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.webkit.PermissionRequest" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> </custom-config-file>
推荐阅读
- c - 如何在 _start 中使用 argv?
- c# - 来自 API 的 JsonConvert.DeserializeObject 对象,使用 Webclient 可能是 2 种对象类型之一
- python - 如何让程序在 Python 中完成后重新运行
- html - 全新的 CSS,无法弄清楚如何为我的每个 html 段落正确编码不同的类/属性值
- django-rest-framework - 类型错误:+= 不支持的操作数类型:“datetime.timedelta”和“NoneType”
- html - 如何使 html 灯箱响应?
- google-apps-script - Google脚本仅使用值和格式复制工作表
- html - 如何在引导程序 4 中创建响应式布局
- git - 推送到 GitHub 时远程挂断
- javascript - 如何在不使用 setTimeout 的情况下这样做?