123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- // components/agora/agora.ts
- // import * as AgoraMiniappSDK from '../../utils/Agora_Miniapp_SDK_for_WeChat.js'
- import * as AgoraMiniappSDK from "agora-miniapp-sdk";
- import { ComponentWithComputed, behavior } from 'miniprogram-computed'
- interface ConfigPropType {
- sdkAppId: string
- token: string
- chanelName: string
- userId: string
- rtcSDKInit: boolean
- }
- type ConfigProp = {
- type: ObjectConstructor,
- value: ConfigPropType
- }
- ComponentWithComputed({
- /**
- * 组件的属性列表
- */
- behaviors: [behavior],
- properties: {
- config: <ConfigProp>{
- type: Object,
- value: {}
- },
- init: {
- type: Boolean,
- value: false
- },
- muted: {
- type: Boolean,
- value: false
- }
- },
- watch: {
- 'config.**': function (obj) {
- console.error('watch-config', obj)
- if (obj.sdkAppId.length > 0) {
- this.setData({
- config: obj
- }, () => {
- if (obj.rtcSDKInit) {
- this.initRTC();
- }
- })
- }
- },
- 'muted': function (val) {
- console.error('watch-muted', val)
- this.onMute(val);
- }
- },
- /**
- * 组件的初始数据
- */
- data: {
- hostRtmpAdress: "",
- client: {} as AgoraMiniappSDK.Client,
- config: {} as ConfigPropType,
- isInit: false,
- muted: false,
- debug: false,
- uid: "", //当前Uid
- media: [] as any[],
- },
- lifetimes: {
- attached(): void {
- console.log('attached agrora');
- },
- detached(): void {
- console.log('detached agrora');
- if (this.data.client) {
- this.data.uid = ''
- if ('leave' in this.data.client) {
- this.data.client.leave();
- }
- }
- }
- },
- /**
- * 组件的方法列表
- */
- methods: {
- setDataAsync(data: any): Promise<void> {
- return new Promise(resolve => void this.setData(data, resolve))
- },
- async initRTC() {
- try {
- if (!this.data.isInit) {
- this.data.isInit = true
- //@ts-ignore
- let client: AgoraMiniappSDK.Client = new AgoraMiniappSDK.Client();
- // this.data.client = client
- //@ts-ignore
- AgoraMiniappSDK.LOG.setLogLevel(-1);
- await this.setDataAsync({ client: client });
- this.subscribeEvents();
- await client.init(this.data.config.sdkAppId);
- console.warn('join--config', this.data.config);
- await client.setRole('broadcaster')
- let uid
- if (!this.data.isReconnect) {
- uid = await client.join(this.data.config.token, this.data.config.chanelName, this.data.config.userId, true, 1);
- } else {
- uid = await client.rejoin(this.data.config.token, this.data.config.chanelName, this.data.config.userId, [this.data.config.userId], true, 1);
- }
- let url = await client.publish();
- console.log('url', url)
- this.setData({
- uid: uid,
- isReconnect: false
- });
- let ts = new Date().getTime();
- this.data.uid = uid;
- this.addMedia(0, this.data.uid, url, {
- key: ts
- });
- }
- } catch (error) {
- console.error('initRTC-error', error)
- let code = error.code || 0;
- if (code == 903 || code == 904 || code === 501 || code === 431) {
- this.reconnect();
- }
- }
- },
- async reconnect() {
- await this.setDataAsync({ isInit: false })
- console.warn('reconnect');
- if (this.data.client) {
- this.data.client.destroy();
- }
- await this.setDataAsync({ isReconnect: true });
- this.triggerEvent('reconnect');
- // await this.initRTC();
- },
- async onMute(muted: boolean) {
- if (muted) {
- this.data.isInit && await this.data.client.muteLocal('audio')
- } else {
- this.data.isInit && await this.data.client?.unmuteLocal('audio')
- }
- this.setData({
- muted: muted
- })
- },
- /**
- * return player component via uid
- */
- getPlayerComponent(uid: string | number) {
- const agoraPlayer = this.selectComponent(`#rtc-player-${uid}`);
- return agoraPlayer;
- },
- onPusherNetstatus: function (e: any) {
- this.data.client.updatePusherNetStatus(e.detail);
- },
- onPusherStatechange: function (e: any) {
- this.data.client.updatePusherStateChange(e.detail);
- },
- addMedia(mediaType: number, uid: string | number, url: string, options: any) {
- console.log(`add media ${mediaType} ${uid} ${url}`);
- let media = this.data.media || [];
- if (mediaType === 0) {
- //pusher
- media.splice(0, 0, {
- key: options.key,
- type: mediaType,
- uid: `${uid}`,
- holding: false,
- url: url,
- left: 0,
- top: 0,
- width: 0,
- height: 0
- });
- } else {
- //player
- media.push({
- key: options.key,
- rotation: options.rotation,
- type: mediaType,
- uid: `${uid}`,
- holding: false,
- url: url,
- left: 0,
- top: 0,
- width: 0,
- height: 0
- });
- }
- this.refreshMedia(media);
- },
- /**
- * update media object
- * the media component will be fully refreshed if you try to update key
- * property.
- */
- refreshMedia(media: any[]): Promise<void> {
- return new Promise((resolve) => {
- console.log(`updating media: ${JSON.stringify(media)}`);
- this.setData({
- media: media
- }, () => {
- resolve();
- });
- });
- },
- updateMedia(uid: string | number, options: any) {
- console.log(`update media ${uid} ${JSON.stringify(options)}`);
- let media = this.data.media || [];
- let changed = false;
- for (let i = 0; i < media.length; i++) {
- let item = media[i];
- if (`${item.uid}` === `${uid}`) {
- media[i] = Object.assign(item, options);
- changed = true;
- console.log(`after update media ${uid} ${JSON.stringify(item)}`)
- break;
- }
- }
- },
- onPlayerNetstatus: function (e: any) {
- // 遍历所有远端流进行数据上报
- let allPlayerStream = this.data.media.filter(m => m.uid !== this.data.uid);
- allPlayerStream.forEach((item: any) => {
- this.data.client.updatePlayerNetStatus(item.uid, e.detail);
- });
- },
- onPlayerStatechange: function (e) {
- let allPlayerStream = this.data.media.filter(m => m.uid !== this.data.uid);
- // 这里 需要去获取所有远端流的 uid
- allPlayerStream.forEach((item: any) => {
- this.data.client.updatePlayerStateChange(item.uid, e.detail);
- });
- },
- /**
- * remove media from view
- */
- removeMedia(uid: string | number) {
- console.log(`remove media ${uid}`);
- let media = this.data.media || [];
- media = media.filter((item: any) => {
- return `${item.uid}` !== `${uid}`
- });
- if (media.length !== this.data.media.length) {
- this.refreshMedia(media);
- } else {
- console.log(`media not changed: ${JSON.stringify(media)}`)
- // return Promise.resolve();
- }
- },
- /**
- * 注册stream事件
- */
- subscribeEvents() {
- /**
- * sometimes the video could be rotated
- * this event will be fired with ratotion
- * angle so that we can rotate the video
- * NOTE video only supportes vertical or horizontal
- * in case of 270 degrees, the video could be
- * up side down
- */
- // this.data.client.on("video-rotation", (e) => {
- // console.log(`video rotated: ${e.rotation} ${e.uid}`)
- // setTimeout(() => {
- // const player = this.getPlayerComponent(e.uid);
- // player && player.rotate(e.rotation);
- // }, 1000);
- // });
- /**
- * fired when new stream join the channel
- */
- this.data.client.on("stream-added", async (e) => {
- let uid = e.uid;
- const ts = new Date().getTime();
- console.warn(`stream ${uid} added `);
- /**
- * subscribe to get corresponding url
- */
- const { url, rotation } = await this.data.client.subscribe(uid);
- let media = this.data.media || [];
- let matchItem = null;
- for (let i = 0; i < media.length; i++) {
- let item = this.data.media[i];
- if (`${item.uid}` === `${uid}`) {
- //if existing, record this as matchItem and break
- matchItem = item;
- break;
- }
- }
- if (!matchItem) {
- //if not existing, add new media
- this.addMedia(1, uid, url, {
- key: ts,
- rotation: rotation
- })
- } else {
- // if existing, update property
- // change key property to refresh live-player
- this.updateMedia(matchItem.uid, {
- url: url,
- key: ts,
- });
- }
- });
- /**
- * remove stream when it leaves the channel
- */
- this.data.client.on("stream-removed", e => {
- let uid = e.uid;
- console.warn(`stream ${uid} removed`);
- this.removeMedia(uid);
- });
- /**
- * when bad thing happens - we recommend you to do a
- * full reconnect when meeting such error
- * it's also recommended to wait for few seconds before
- * reconnect attempt
- */
- this.data.client.on("error", err => {
- let errObj = err || {};
- let code = errObj.code || 0;
- let reason = errObj.reason || "";
- console.warn(`error: ${code}, reason: ${reason}`);
- // wx.showToast({
- // title: `argora有错误,code:${code}`,
- // icon: 'none',
- // duration: 5000
- // });
- if (code === 501 || code === 904) {
- this.reconnect();
- }
- });
- /**
- * there are cases when server require you to update
- * player url, when receiving such event, update url into
- * corresponding live-player, REMEMBER to update key property
- * so that live-player is properly refreshed
- * NOTE you can ignore such event if it's for pusher or happens before
- * stream-added
- */
- this.data.client.on('update-url', e => {
- console.log(`update-url: ${JSON.stringify(e)}`);
- let uid = e.uid;
- let url = e.url;
- let ts = new Date().getTime();
- if (`${uid}` === `${this.data.uid}`) {
- // if it's not pusher url, update
- console.log(`ignore update-url`);
- } else {
- this.updateMedia(uid, {
- url: url,
- key: ts,
- });
- }
- });
- this.data.client.on("token-privilege-will-expire", () => {
- console.warn("当前 token 即将过期,请更新 token");
- // this.data.client.renewToken();
- this.reconnect();
- });
- this.data.client.on("token-privilege-did-expire", () => {
- console.warn("当前 token 已过期,请更新 token 并重新加入频道");
- this.reconnect();
- });
- }
- }
- })
|