• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

腾讯TRTC产品初体验web

武飞扬头像
凌霸哥
帮助2

简介

第一次听到有人在群里吹水TRTC这个词还以为又是啥狠活儿,后来仔细看了一下它的产品简介,发现它只是腾讯实时音视频的英文简写,实时音视频并不算太新奇的技术,它相对来说是一个目前比较常见的技术手段,由于疫情导致学校网课,居家办公,直播带货等这类对信息实时性要求较高的业务场景增多,所以导致目前对实时音视频做定向开发的产品需求一直很旺盛,本文从一个第一次接触TRCT产品的小白开始实现简单实时音频Demo

登入腾讯云

链接: 注册腾讯云账号.
学新通
首页找到实时音视频或者直接点这里进入
学新通
应用管理创建一个应用这里我用的是zxzRtcz这个应用
学新通
记录SDKAppID这串数字,前端开发中需要,前端开发不需要使用密钥SecretKey
学新通

代码编程

这里我用的Vue3初始化项目做初始化工程脚手架
学新通
npm集成TRTC js sdk

npm install trtc-js-sdk --save

在项目脚本里导入模块

import TRTC from 'trtc-js-sdk'

SDK 使用逻辑概览

您在使用 TRTC Web SDK 时,会接触到以下概念:

  • Client 类,其实例代表一个本地客户端。Client 的对象方法提供了加入通话房间、发布本地流、订阅远端流等功能。
  • Stream 类,其实例代表一个音视频流对象,包括本地音视频流对象 LocalStream 和远端音视频流对象 RemoteStream。Stream 的对象方法主要提供对音视频流的控制操作,包括音频和视频的播放控制。

实现音视频通话基本逻辑

  1. 调用 TRTC.createClient() 方法创建 client 对象。
  2. 调用 client.join() 进入音视频通话房间。
  3. 您进入房间成功后,可以发布本地流,远端用户可以订阅您的流:
    1. 调用 TRTC.createStream() 创建本地音视频流。
    2. 调用 localStream.initialize() 初始化本地音视频流,开始获取系统设备权限,采集音视频。
    3. 在本地流初始化成功后,调用 client.publish() 方法发布本地流。
  4. 当一个远端用户加入房间,并发布音视频流时,您可以订阅远端流进行播放:
    1. 在您进房前监听 client.on(‘stream-added’) 事件,就能收到所有远端用户的推流事件。
    2. 调用 client.subscribe() 方法订阅远端流。
    3. 触发订阅成功事件 client.on(‘stream-subscribed’) 后,调用 remoteStream.play() 方法播放。

下图展示了实现音视频通话全过程的基础 API 调用流程

学新通

创建 Client 对象

const client = TRTC.createClient({ mode: 'rtc', sdkAppId, userId, userSig })
  • mode: 实时音视频通话模式,设置为 ‘rtc’。
  • sdkAppId: 您在腾讯云创建的音视频应用的 sdkAppId。
  • userId: 用户 ID,由您指定。
  • userSig: 用户签名,参考 获取临时userSig,或者部署 userSig 签发服务(需后端介入)。

获取临时userSig

学新通

进入音视频通话房间

调用 client.join() 进入音视频通话房间。通常在开始通话按钮的点击回调里进行调用。 关键参数:

try {
  await client.join({ roomId: 8888 });
  console.log('进房成功');
} catch (error) {
  console.error('进房失败 '   error);
}
  • roomId:房间 ID,由您指定,通常是生成唯一的房间ID。 更详细的参数说明参考接口文档 client.join()。

发布本地流和订阅远端流

创建本地音视频流

const localStream = TRTC.createStream({ userId, audio: true, video: true });

使用 TRTC.createStream() 方法创建本地音视频流。 以下实例从摄像头及麦克风中采集音视频流,参数设置如下:

  • userId:用户 ID
  • audio:是否开启音频
  • video:是否开启视频

初始化本地音视频流

接下来调用 initialize() 初始化本地音视频流。

try {
  await localStream.initialize();
  console.log('初始化本地流成功');
} catch (error) {
  console.error('初始化本地流失败 '   error);
}

发布本地音视频流

在本地流初始化成功后,调用 publish() 方法发布本地流。

try {
  await client.publish(localStream);
  console.log('本地流发布成功');
} catch (error) {
  console.error('本地流发布失败 '   error);
}

订阅远端音视频流

远端流通过监听事件 client.on(‘stream-added’) 获得,请在 client.join() 进房前注册该事件,确保您不会错过远端用户进房通知。 收到上述事件后要通过 client.subscribe() 订阅远端音视频流。

client.on('stream-added', event => {
  const remoteStream = event.stream;
  console.log('远端流增加: '   remoteStream.getId());
  //订阅远端流
  client.subscribe(remoteStream);
});
client.on('stream-subscribed', event => {
  const remoteStream = event.stream;
  console.log('远端流订阅成功:'   remoteStream.getId());
  // 播放远端流,传入的元素 ID 必须是页面里存在的 div 元素
  remoteStream.play('remote_stream-'   remoteStream.getId());
});

播放音视频流

在本地流初始化成功的回调中,或远端流订阅成功事件回调中,通过调用 stream.play() 方法在网页中播放音视频。play方法接受一个 div 元素 ID 作为参数,SDK 内部会在该 div 元素下自动创建相应的音视频标签并在其上播放音视频。

  • 初始化本地流成功时播放本地流。
try {
  await localStream.initialize();
  console.log('初始化本地流成功');
  // 播放本地流,'local_stream' 是在 DOM 中的一个 div 标签的 ID
  localStream.play('local_stream');
} catch (error) {
  console.error('初始化本地流失败 '   error);
}
  • 订阅远端流成功时播放远端流。
client.on('stream-subscribed', event => {
  const remoteStream = event.stream;
  console.log('远端流订阅成功:'   remoteStream.getId());
  // 如果您遇到播放失败的问题,需要使用 remoteStream 监听 error 并处理 0x4043 浏览器限制自动播放的问题
  remoteStream.on('error', error => {
    const errorCode = error.getCode();
    if (errorCode === 0x4043) {
      // PLAY_NOT_ALLOWED, 引导用户手势操作并调用 stream.resume 恢复音视频播放,
      // 在点击回调里调用 remoteStream.resume() 进行恢复播放。
    }
  });
  // 播放远端流,传入的元素 ID 必须是页面里存在的 div 元素
  remoteStream.play('remote_stream-'   remoteStream.getId());
});

退出音视频通话房间

通话结束时调用 client.leave() 方法退出音视频通话房间,整个音视频通话会话结束。

await client.leave(); 
// 退房成功,如果没有调用 client.destroy(),可再次调用 client.join 重新进房开启新的通话
// 调用 destroy() 结束当前 client 的生命周期
client.destroy();

完整代码

LoginView.vue

<template>
  <div class="about">
    <h1 style="margin-left: 20px;">这里是简易登陆也面</h1>
    <h2 style="margin-left: 20px;">请选择你的角色:</h2>
    <el-radio-group v-model="radio" style="margin-left: 20px;">
      <el-radio v-for="(item, index) in userList" :key="index" :label="index" size="large" border>{{ item.nikeName }}</el-radio>
    </el-radio-group>
    <div style="margin-left: 20px; padding-top: 30px;">
      <el-button @click="login">登陆</el-button>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  data() {
    return {
      radio: 0,
      userList: [
        {
          userId: 'zxz0',
          nikeName: '用户0',
          userSig: ''
        },
        {
          userId: 'zxz1',
          nikeName: '用户1',
          userSig: ''
        },
        {
          userId: 'zxz2',
          nikeName: '用户2',
          userSig: ''
        }
      ]
    }
  },
  methods: {
    login() {
      const obj = this.$router.resolve({ path: '/home', query: { index: this.radio} })
      window.open(obj.href, '_blank')
    }
  }
})
</script>
<style>
@media (min-width: 1024px) {
  .about {
    min-height: 100vh;
  }
}
</style>

学新通

学新通

HomeView.vue

<template>
  <main>
    <div class="use-btn">
      <el-button @click="logout()">返回</el-button>
    </div>
    远程视频:
    <div id="remoteStream"></div>
    本地视频:
    <div id="localStream"></div>
    <img id="img" style="display:none" src="@/assets/background.jpeg" alt="">
  </main>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted } from 'vue'
import { getToken, removeToken } from '@/utils/auth'
import { getCurrentInstance } from 'vue'
import RTCBeautyPlugin from 'rtc-beauty-plugin'
const beautyPlugin = new RTCBeautyPlugin()
beautyPlugin.setBeautyParam({ beauty: 0.5, brightness: 0.5, ruddy: 0.5 })
const proxy = getCurrentInstance()?.proxy
const $router = proxy?.$router
const $route = proxy?.$route
const $Trtc = proxy?.$Trtc
let client: { join: (arg0: { roomId: number; }) => any; publish: (arg0: any) => any; on: (arg0: string, arg1: { (event: any): void; (event: any): void; }) => void; subscribe: (arg0: any) => void; leave: () => any; destroy: () => void; }
let localStream: { initialize: () => any; play: (arg0: string) => void; close: () => void; }
const userList = [
  {
    userId: 'zxz0',
    nikeName: '用户0',
    userSig: ''
  },
  {
    userId: 'zxz1',
    nikeName: '用户1',
    userSig: ''
  },
  {
    userId: 'zxz2',
    nikeName: '用户2',
    userSig: ''
  }
]
async function startStrem() {
  try {
    await client.join({ roomId: 8888 })
    await localStream.initialize()
    await beautyPlugin.loadResources()
    const stream = await beautyPlugin.generateStream({ 
      localStream: localStream,	  
      type: 'virtual',
      img: document.getElementById('img')
    })
    stream.play('localStream')
    await client.publish(stream)
  } catch (error) {
    console.error('失败'   error)
  }
}
function logout() {
  destroy()
  $router?.push('/login')
} 
onMounted(() => {
  const index = Number($route?.query.index) || 0
  const { userId, userSig } = userList[index]
  client = $Trtc.createClient({
    mode: 'rtc',
    sdkAppId: 1400772732,
    userId,
    userSig
  })
  client.on('stream-added', (event: any) => {
    const remoteStream = event.stream
    //订阅远端流
    client.subscribe(remoteStream)
  })
  client.on('stream-subscribed', (event: any) => {
    // 远端流订阅成功
    const remoteStream = event.stream
    remoteStream.play('remoteStream')
  })
  localStream = $Trtc.createStream({ userId, audio: true, video: true })
  startStrem()
})
async function destroy() {
  try {
  // 停止本地流预览
  localStream.close()
  await client.leave()
  // 退房成功,如果没有调用 client.destroy(),可再次调用 client.join 重新进房开启新的通话
  // 调用 destroy() 结束当前 client 的生命周期
  client.destroy()
  console.log('销毁成功!')
  } catch (error) {
    
  }
}
onUnmounted(() => {
  destroy()
})
</script>
<style lang="css">
.use-btn{
  display: flex;
  justify-content: flex-end;
  padding: 20px;
}
</style>

学新通

学新通
gitee项目地址

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfhfhfi
系列文章
更多 icon
同类精品
更多 icon
继续加载