Commit 491d1c00 by wxl

验证视频通话功能

parent 9432799a
import { AgoraAppStore } from "any-hooks/types/agora";
import { onMounted, watch } from "vue";
import { useInjector, useState } from "vue-vulcan";
import { AGORA_APP_SDK } from "../communication/token";
interface AgoraStreamItem {
url?: string;
uid: string;
}
// type AgoraState = 'unready' | 'inited' | 'joined';
/** 基于声网sdk封装,由于多平台特性,请在根组件将对应平台的声网SDK对象以及appid通过useProvider提供; */
export function useAgoraClient() {
const [agoraErr, setError] = useState(null);
const [streamList, setStream] = useState<AgoraStreamItem[]>([]);
const { appid, client } = useInjector<AgoraAppStore>(AGORA_APP_SDK);
onMounted(() => {
client.init(appid, subscribeRemoteStream, setError);
})
const joinChannelWithVideo = (token: string, cid: string, uid: string) => {
client.join(
token,
cid,
uid,
pushVideoStream,
setError
);
}
//推送本地视频流
const [localPushurl, setPushUrl] = useState('');
const pushVideoStream = () => {
client.publish( url => setPushUrl(url));
}
//监听远程视频流
const subscribeRemoteStream = () => {
client.on('stream-added', evt => {
client.subscribe(
evt.uid,
url => updateStremList('add', {uid: evt.uid, url}),
setError
)
});
client.on('stream-removed', evt => updateStremList('remove', {uid: evt.uid}));
}
watch(streamList, console.log)
// 根据uid来新增或移除远端视频流列表
const updateStremList = (action: 'add' | 'remove', input: AgoraStreamItem) => {
switch(action) {
case 'add':
setStream(streamList.value.concat(input));
break;
case 'remove':
const index = streamList.value.findIndex(item => item.uid === input.uid);
index && setStream(streamList.value.splice(index, 1));
break;
}
}
// 监听来自Agora Client的错误提示
watch(agoraErr, err => {
console.error(err)
})
return {
localPushurl,
streamList,
joinChannelWithVideo
}
}
\ No newline at end of file
export const AGORA_APP_STORE = Symbol('agora app store'); export const AGORA_APP_SDK = Symbol('agora app sdk');
export const CUSTOME_SOCKET = Symbol('custome socket'); export const CUSTOME_SOCKET = Symbol('custome socket');
......
import { AgoraAppStore } from "any-hooks/types/agora";
import { useInjector } from "vue-vulcan";
import { AGORA_APP_STORE } from "./token";
/** 基于声网sdk封装,由于多平台特性,请在根组件通过useProvider和对应平台的SDK提供agora Client对象以及相关appid; */
export function useAgoraClient() {
const { appid, client } = useInjector<AgoraAppStore>(AGORA_APP_STORE);
return {
appid,
client
}
}
\ No newline at end of file
import { watch } from "vue"; import { watch } from "vue";
import { BehaviorSubject } from "rxjs";
import { useRequest, useState } from "vue-vulcan"; import { useRequest, useState } from "vue-vulcan";
import { UserData } from "any-hooks/types/user";
interface ChannelData { interface ChannelData {
channel_id: string; channel_id: string;
agora_token: string; agora_token: string;
members: string[]; members?: UserData[];
} }
/** 频道中心功能,可以创建频道,并保存当前频道的信息,供呼叫中心、会议中心使用(目前只允许同一时间仅存在一个频道) */
export function useChannelStore() { export function useChannelStore() {
const [currentChannel, setCurrent] = useState<ChannelData>(null); const [currentChannel, setCurrent] = useState<ChannelData>(null);
const [channelInfo, request] = useRequest<ChannelData>('/getAgoraToken', {auto: false}); const [channelInfo, request] = useRequest<ChannelData>('/getAgoraToken', {auto: false});
const ready$ = new BehaviorSubject<boolean>(false);
const createChannel = () => { const createChannel = () => {
return request() return request()
} }
const joinCallingChannel = (id: string) => { const joinCallingChannel = (cid: string) => {
request({channel_id: id}) request({channel_id: cid});
}
const onReady = ( callback: () => void) => {
ready$.subscribe( r => { r && callback() })
} }
watch(channelInfo, val => { watch(channelInfo, val => {
...@@ -33,7 +29,6 @@ export function useChannelStore() { ...@@ -33,7 +29,6 @@ export function useChannelStore() {
return { return {
currentChannel, currentChannel,
joinCallingChannel, joinCallingChannel,
createChannel, createChannel
onReady
} }
} }
\ No newline at end of file
import { useAuthData } from "any-hooks/auth/useAuthData";
import { useAgoraClient } from "any-hooks/common/useAgoraClient";
import { computed, watch } from "vue";
import { useInjector } from "vue-vulcan";
import { useChannelStore } from "./useChannelStore";
/** 会议中心功能, 该功能在呼叫功能生效后使用,通过调用agoraSDK实现多人视频会议、语音会议的功能 */
export function useMeetingCenter() {
const { currentChannel } = useInjector(useChannelStore);
const { authData } = useInjector(useAuthData)
const {joinChannelWithVideo, streamList, localPushurl} = useAgoraClient();
// const meetingMembers = computed()
watch(currentChannel, channel => {
joinChannelWithVideo(
channel.agora_token,
channel.channel_id,
authData.value.id
)
})
return {
streamList,
localPushurl
}
}
\ No newline at end of file
...@@ -15,8 +15,8 @@ enum NetStates { ...@@ -15,8 +15,8 @@ enum NetStates {
export function useNetSocketCenter() { export function useNetSocketCenter() {
const { authData } = useInjector(useAuthData); const { authData } = useInjector(useAuthData);
const { connect, send, currentMsg, startHeartConnect } = useSocket<AnyRemoteSocketMessage>();
const [ netState, setNetState ] = useState<NetStates>(0); const [ netState, setNetState ] = useState<NetStates>(0);
const { connect, send, currentMsg, startHeartConnect } = useSocket<AnyRemoteSocketMessage>();
watch(authData, data => { watch(authData, data => {
if(!data) return; if(!data) return;
......
type AgoraEventType = 'stream-added' | 'stream-removed' | 'update-url"'
export interface AgoraSdkClient { export interface AgoraSdkClient {
init: (cb: any) => void; init: (appid: string, success?: any, err?: any) => void;
join: (cb: any) => void; join: (token: string, cid: string, uid: string, success?: any, err?: any) => void;
rejoin: (cb: any) => void; rejoin: (cb: any) => void;
publish: (cb: any) => void; publish(onSuccess: (url: string) => void, onFailure?: (err: { code: number; reason: string }) => void): void;
on: (cb: any) => void; on(event: "error", callback: (evt: { code: number; reason: string }) => void): void;
on(event: AgoraEventType, callback: (evt: { uid: string, url?: string }) => void): void;
off: (cb: any) => void; off: (cb: any) => void;
subscribe(uid: string, onSuccess: (url: string) => void, onFailure?: (err: any) => void): void
leave: (cb: any) => void; leave: (cb: any) => void;
destory: (cb: any) => void; destory: (cb: any) => void;
} }
export interface AgoraAppStore { export interface AgoraAppStore {
appid: string; appid: string;
client: AgoraSdkClient; client: AgoraSdkClient;
} }
...@@ -6,4 +6,6 @@ export interface UserData { ...@@ -6,4 +6,6 @@ export interface UserData {
avatar?: string; avatar?: string;
permission?: string; permission?: string;
token?: string; token?: string;
is_signin?: '1' | '2';
is_calling?: '1' | '0';
} }
\ No newline at end of file
.layout {
height: 100%;
width: 100%;
}
\ No newline at end of file
...@@ -14,6 +14,8 @@ import { useCallCenter } from 'any-hooks/communication/useCallCenter'; ...@@ -14,6 +14,8 @@ import { useCallCenter } from 'any-hooks/communication/useCallCenter';
import { useChannelStore } from 'any-hooks/communication/useChannelStore'; import { useChannelStore } from 'any-hooks/communication/useChannelStore';
import { useNetSocketCenter } from 'any-hooks/communication/useNetSocketCenter'; import { useNetSocketCenter } from 'any-hooks/communication/useNetSocketCenter';
import { useCallerListener } from './hooks/call/useCallerListener'; import { useCallerListener } from './hooks/call/useCallerListener';
import { useAgoraSDK } from './hooks/meeting/useAgoraSDK';
import { useMeetingCenter } from 'any-hooks/communication/useMeetingCenter';
const App = createApp({ const App = createApp({
onShow () {}, onShow () {},
...@@ -28,8 +30,10 @@ const App = createApp({ ...@@ -28,8 +30,10 @@ const App = createApp({
useCustomeSocket, //自定义基于taro的socket通讯接口,覆盖useSocket默认的websokcet useCustomeSocket, //自定义基于taro的socket通讯接口,覆盖useSocket默认的websokcet
useNetSocketCenter, //全局的socket连接中心 useNetSocketCenter, //全局的socket连接中心
useChannelStore, //全局的频道信息 useChannelStore, //全局的频道信息
useCallCenter, //全局的多人呼叫, useCallCenter, //全局的多人呼叫
useCallerListener //在整个APP生命周期内监听远程联系人的呼叫请求 useCallerListener, //在整个APP生命周期内监听远程联系人的呼叫请求
useAgoraSDK, //提供声网skd配置信息
useMeetingCenter //全局的多人会议中心
); );
authorize({ scope: 'scope.camera' }); authorize({ scope: 'scope.camera' });
useAuthCheck(); useAuthCheck();
......
...@@ -24,7 +24,7 @@ export function useCallerListener() { ...@@ -24,7 +24,7 @@ export function useCallerListener() {
}) })
break; break;
case 'Hangup': case 'Hangup':
showToast({title: '对方已取消呼叫,您可以关闭呼叫对话框', icon: 'none'}); showToast({title: '对方取消了呼叫,您可以点击接受关闭对话框', icon: 'none'});
break; break;
} }
}) })
......
import * as AgoraMiniappSDK from 'src/libs/Agora_SDK_for_WeChat';
import { AGORA_APP_SDK } from "any-hooks/communication/token";
import { AgoraAppStore } from 'any-hooks/types/agora';
const appid = '0a67966ff4ae4eb3b32446df0151e16a';
const client = new AgoraMiniappSDK.Client();
export function useAgoraSDK(): AgoraAppStore {
return { appid, client }
}
useAgoraSDK.token = AGORA_APP_SDK;
\ No newline at end of file
<script setup> <script setup>
import { useMeetingCenter } from 'any-hooks/communication/useMeetingCenter';
import { onMounted, watch } from 'vue'; import { onMounted, watch } from 'vue';
import { useInjector } from 'vue-vulcan';
const { streamList, localPushurl } = useInjector(useMeetingCenter);
</script> </script>
<template> <template>
<view class ="meeting-container"> <view class ="meeting-container layout">
<!-- <view <view
class="players" class="players"
v-for="(item, key) in videoMeeting.streams.value" v-for="(item, key) in streamList"
:key="key" :key="key"
> >
<live-player v-if="item.uid" :src="item.url" mode="RTC" style="width: 100%;height:200px;" /> <live-player v-if="item.uid" :src="item.url" mode="RTC" style="width: 100%;height:200px;" waiting-image="https://webdemo.agora.io/away.png"/>
<live-pusher v-else :autopush="true" @error="onError" @statechange="net" :url="item.url" :local-mirror="'enable'" mode="RTC" style="width: 100%;height:100px;" /> </view>
<live-pusher :autopush="true" :url="localPushurl" :local-mirror="'enable'" mode="RTC" style="width: 100%;height:100px;" />
</view> -->
</view> </view>
</template> </template>
<style>
page{
width: 100%;
height: 100%;
}
.meeting-container{
background: #333;
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment