fix(amap):集成webrtc 到自有代码
This commit is contained in:
parent
210df9fa06
commit
32c9bd2381
|
@ -81,7 +81,7 @@ export const items = [
|
||||||
{ label: `部门管理`, key: "/admin/dep" },
|
{ label: `部门管理`, key: "/admin/dep" },
|
||||||
{ label: "系统设置", key: "/admin/sys/setting" },
|
{ label: "系统设置", key: "/admin/sys/setting" },
|
||||||
{ label: "光荣牌审核", key: "/admin/sys/gp" },
|
{ label: "光荣牌审核", key: "/admin/sys/gp" },
|
||||||
{ label: "评优审核", key: "/admin/sys/gp" },
|
{ label: "评优审核", key: "/admin/sys/exce_compet" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
|
@ -10,6 +10,7 @@ class MapUtl {
|
||||||
|
|
||||||
static addMaker(data: any) {
|
static addMaker(data: any) {
|
||||||
const { lng, lat, title, users } = data;
|
const { lng, lat, title, users } = data;
|
||||||
|
if (MapUtl.loadMap === null) return;
|
||||||
const marker = new MapUtl.loadMap.Marker({
|
const marker = new MapUtl.loadMap.Marker({
|
||||||
position: new MapUtl.loadMap.LngLat(lng, lat),
|
position: new MapUtl.loadMap.LngLat(lng, lat),
|
||||||
title: title,
|
title: title,
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import BTable from "@/components/b_table";
|
||||||
|
import { UserDataType } from "@/model/userModel";
|
||||||
|
import { Button } from "antd";
|
||||||
|
import { Store } from "antd/es/form/interface";
|
||||||
|
import { ColumnsType } from "antd/lib/table";
|
||||||
|
import { inject, observer } from "mobx-react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const ExceCompet = (props: Store) => {
|
||||||
|
const { exceCompetStore } = props;
|
||||||
|
useEffect(() => {
|
||||||
|
exceCompetStore.getlist();
|
||||||
|
}, [exceCompetStore]);
|
||||||
|
const columns: ColumnsType<UserDataType> = [
|
||||||
|
{ title: "评优标题", dataIndex: "title" },
|
||||||
|
{ title: "内容", dataIndex: "content" },
|
||||||
|
{
|
||||||
|
title: "评优申请人",
|
||||||
|
dataIndex: "users",
|
||||||
|
render: (users) => <span>{users?.user_name}</span>
|
||||||
|
},
|
||||||
|
{ title: "申请积分", dataIndex: "reviewer_score" },
|
||||||
|
{ title: "申请时间", dataIndex: "created_at" },
|
||||||
|
{ title: "描述", dataIndex: "desc" },
|
||||||
|
{ title: "审核状态", dataIndex: "status" },
|
||||||
|
{ title: "审核人", dataIndex: "reviewer_identity" },
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
dataIndex: "id",
|
||||||
|
render: (any, record) => (
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
// edit(record);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
审核
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<BTable
|
||||||
|
store={exceCompetStore}
|
||||||
|
columns={columns}
|
||||||
|
dataSource={exceCompetStore.list}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default inject("exceCompetStore")(observer(ExceCompet));
|
|
@ -48,7 +48,7 @@ const Home = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
<MapContainer />
|
<MapContainer />
|
||||||
<div className="map_video_container">
|
<div className="map_video_container">
|
||||||
<Video />
|
{/* <Video /> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="map_container_r">
|
<div className="map_container_r">
|
||||||
<HomeRight />
|
<HomeRight />
|
||||||
|
|
|
@ -20,9 +20,7 @@ const Ec = (props: Store) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const callphone = (record: any) => {
|
|
||||||
webRTC.calls(record.value);
|
|
||||||
};
|
|
||||||
const [value, setValue] = useState<UserValue[]>([]);
|
const [value, setValue] = useState<UserValue[]>([]);
|
||||||
async function fetchUserList(username: string): Promise<UserValue[]> {
|
async function fetchUserList(username: string): Promise<UserValue[]> {
|
||||||
return usrStore.serchUser(username).then((res) => {
|
return usrStore.serchUser(username).then((res) => {
|
||||||
|
@ -73,8 +71,8 @@ const Ec = (props: Store) => {
|
||||||
<PhoneTwoTone
|
<PhoneTwoTone
|
||||||
style={{ fontSize: "20px" }}
|
style={{ fontSize: "20px" }}
|
||||||
onClick={(items) => {
|
onClick={(items) => {
|
||||||
webRTC.init();
|
webRTC.init(item.key);
|
||||||
callphone(item);
|
webRTC.calls();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ const videoJsOptions = {
|
||||||
fluid: true,
|
fluid: true,
|
||||||
sources: [
|
sources: [
|
||||||
{
|
{
|
||||||
src: "http://183.221.86.205:18000/hls/stream_1_0/playlist.m3u8",
|
src: "https://sprh.hswzct.cn:4443/hls/stream_1_0/playlist.m3u8",
|
||||||
type: "application/x-mpegURL",
|
type: "application/x-mpegURL",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -26,6 +26,7 @@ import GloryPlaque from "@/pages/glory_plaque";
|
||||||
import Grid from "@/pages/grid";
|
import Grid from "@/pages/grid";
|
||||||
import Community from "@/pages/community";
|
import Community from "@/pages/community";
|
||||||
import PatrolBrigade from "@/pages/patrolBrigade";
|
import PatrolBrigade from "@/pages/patrolBrigade";
|
||||||
|
import ExceCompet from "@/pages/exce_compet";
|
||||||
export const homeRouter = [
|
export const homeRouter = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
|
@ -148,6 +149,7 @@ export const homeRouter = [
|
||||||
index: true,
|
index: true,
|
||||||
element: <Training />,
|
element: <Training />,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "/admin/whse",
|
path: "/admin/whse",
|
||||||
element: <WhseMgmtRoute />,
|
element: <WhseMgmtRoute />,
|
||||||
|
@ -178,6 +180,11 @@ export const homeRouter = [
|
||||||
index: true,
|
index: true,
|
||||||
element: <GloryPlaque />,
|
element: <GloryPlaque />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/admin/sys/exce_compet",
|
||||||
|
index: true,
|
||||||
|
element: <ExceCompet />,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { action, makeObservable } from "mobx";
|
||||||
|
// 档案
|
||||||
|
import BaseStore from "./baseStore";
|
||||||
|
import { TagDataType } from "@/model/userModel";
|
||||||
|
import baseHttp from "@/service/base";
|
||||||
|
|
||||||
|
class ExceCompetConfig {
|
||||||
|
static LIST: string = "exceCompet/list"
|
||||||
|
static ADD: string = "exceCompet"
|
||||||
|
static DELETE: string = "exceCompet"
|
||||||
|
static EDIT: string = "exceCompet"
|
||||||
|
}
|
||||||
|
class ExceCompetStore extends BaseStore<TagDataType> {
|
||||||
|
constructor() {
|
||||||
|
super(ExceCompetConfig)
|
||||||
|
makeObservable(this, {
|
||||||
|
save: action
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async save(id: string, list: Array<any>) {
|
||||||
|
return await baseHttp.post(ExceCompetConfig.ADD +"/"+ id, {"list":list});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const exceCompetStore = new ExceCompetStore()
|
||||||
|
|
|
@ -25,6 +25,7 @@ import gpStore from './gp';
|
||||||
import { communityStore } from './community';
|
import { communityStore } from './community';
|
||||||
import { gridStore } from './grid';
|
import { gridStore } from './grid';
|
||||||
import { patrolBrigadeStore } from './patrol_brigade';
|
import { patrolBrigadeStore } from './patrol_brigade';
|
||||||
|
import { exceCompetStore } from './exce_compet';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +56,8 @@ const store = {
|
||||||
gpStore,
|
gpStore,
|
||||||
gridStore,
|
gridStore,
|
||||||
communityStore,
|
communityStore,
|
||||||
patrolBrigadeStore
|
patrolBrigadeStore,
|
||||||
|
exceCompetStore
|
||||||
};
|
};
|
||||||
|
|
||||||
export default store;
|
export default store;
|
|
@ -25,11 +25,11 @@
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let ws;
|
let ws, pc, configuration,
|
||||||
let pc;
|
url =
|
||||||
let configuration;
|
'https://rw.quwanya.cn/v1/public/webRtcConfig?service=turn&username=flutter-webrtc',
|
||||||
var url =
|
formId = "admin",
|
||||||
'http://127.0.0.1:12214/v1/public/webRtcConfig?service=turn&username=flutter-webrtc';
|
toId = "01J9T8MP541EJ54KY4505C0S4Y";
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
@ -45,6 +45,123 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const call = () => {
|
const call = () => {
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
||||||
|
.then(stream => {
|
||||||
|
pc = new RTCPeerConnection(configuration)
|
||||||
|
pc.ontrack = function (event) {
|
||||||
|
console.log(event)
|
||||||
|
if (event.track.kind === 'audio') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let el = document.createElement(event.track.kind)
|
||||||
|
el.srcObject = event.streams[0]
|
||||||
|
el.autoplay = true
|
||||||
|
el.controls = true
|
||||||
|
document.getElementById('remoteVideos').appendChild(el)
|
||||||
|
event.track.onmute = function (event) {
|
||||||
|
el.play()
|
||||||
|
}
|
||||||
|
event.streams[0].onremovetrack = ({ track }) => {
|
||||||
|
if (el.parentNode) {
|
||||||
|
el.parentNode.removeChild(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.getElementById('localVideo').srcObject = stream
|
||||||
|
stream.getTracks().forEach(track => pc.addTrack(track, stream))
|
||||||
|
pc.onicecandidate = e => {
|
||||||
|
if (!e.candidate) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "candidate", data: {
|
||||||
|
"to": toId,
|
||||||
|
"from": formId,
|
||||||
|
"description": e.candidate,
|
||||||
|
"media": "video",
|
||||||
|
"session_id": toId + "-" + formId,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
this.send({
|
||||||
|
type: "call",
|
||||||
|
"data": {
|
||||||
|
"to": toId,
|
||||||
|
"from": formId,
|
||||||
|
"description": "call",
|
||||||
|
"media": "video",
|
||||||
|
"session_id": toId + "-" + formId,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
send = (data) => {
|
||||||
|
ws.send(JSON.stringify(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// wss://rw.quwanya.cn/ws
|
||||||
|
initSocket = () => {
|
||||||
|
ws = new WebSocket("wss://rw.quwanya.cn/wsadmin?id=" + formId)
|
||||||
|
ws.addEventListener('open', function (event) {
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "peerRoot", "data": {
|
||||||
|
"name": "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 )",
|
||||||
|
"id": formId,
|
||||||
|
"user_agent": "flutter-webrtc/js"
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
ws.onclose = function (evt) {
|
||||||
|
console.log(evt);
|
||||||
|
}
|
||||||
|
ws.onmessage = function (evt) {
|
||||||
|
let msg = JSON.parse(evt.data)
|
||||||
|
if (!msg) {
|
||||||
|
return console.log('failed to parse msg')
|
||||||
|
}
|
||||||
|
switch (msg.type) {
|
||||||
|
case 'offer':
|
||||||
|
let offer = msg.content.body.description
|
||||||
|
pc.setRemoteDescription(offer)
|
||||||
|
pc.createAnswer().then(answer => {
|
||||||
|
pc.setLocalDescription(answer)
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'answer', data: {
|
||||||
|
'to': msg.content.body.from,
|
||||||
|
'from': formId,
|
||||||
|
'description': { 'sdp': answer.sdp, 'type': answer.type },
|
||||||
|
'session_id': msg.content.body.from + "-" + toId,
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
return
|
||||||
|
case 'candidate':
|
||||||
|
let candidate = msg.content.body.description
|
||||||
|
console.log("candidate1111", msg.content)
|
||||||
|
if (!candidate) {
|
||||||
|
return console.log('failed to parse candidate')
|
||||||
|
}
|
||||||
|
pc.addIceCandidate(candidate)
|
||||||
|
return
|
||||||
|
case "read":
|
||||||
|
pc?.createOffer().then(function (offer) {
|
||||||
|
pc?.setLocalDescription(offer);
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: "offer", "data": {
|
||||||
|
"to": toId,//"31283192",
|
||||||
|
"from": formId,
|
||||||
|
"description": offer,
|
||||||
|
"media": "video",
|
||||||
|
"session_id": formId + "-" + toId,
|
||||||
|
}
|
||||||
|
}),)
|
||||||
|
}).catch(function (error) {
|
||||||
|
// 错误处理
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
return
|
||||||
|
case "call": // 接收到call 初始化 然后发送消息 read
|
||||||
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
||||||
.then(stream => {
|
.then(stream => {
|
||||||
pc = new RTCPeerConnection(configuration)
|
pc = new RTCPeerConnection(configuration)
|
||||||
|
@ -72,76 +189,31 @@
|
||||||
if (!e.candidate) {
|
if (!e.candidate) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ws.send(JSON.stringify({ type: 'candidate', data: e }))
|
|
||||||
}
|
|
||||||
pc?.createOffer().then(function (offer) {
|
|
||||||
pc?.setLocalDescription(offer);
|
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
type: "offer", "data": {
|
type: 'candidate',
|
||||||
"to": "31283192",
|
data: {
|
||||||
"from": "31283191",
|
"to": toId,
|
||||||
"description": offer,
|
"from": formId,
|
||||||
|
"description": e,
|
||||||
"media": "video",
|
"media": "video",
|
||||||
"session_id": "31283192-31283191",
|
"session_id": toId + "-" + formId,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
// socketService.send({ type: 'offer', data: offer })
|
|
||||||
}).catch(function (error) {
|
|
||||||
// 错误处理
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
}).catch((e) => {
|
|
||||||
console.log(e);
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// wss://rw.quwanya.cn/ws
|
|
||||||
initSocket = () => {
|
|
||||||
ws = new WebSocket("ws://127.0.0.1:12214/wsadmin?id=31283192")
|
|
||||||
ws.addEventListener('open', function (event) {
|
|
||||||
ws.send(JSON.stringify({
|
ws.send(JSON.stringify({
|
||||||
type: "peerRoot", "data": {
|
type: "read", "data": {
|
||||||
"name": "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 )",
|
"to": toId,
|
||||||
"id": "31283192",
|
"from": formId,
|
||||||
"user_agent": "flutter-webrtc/js"
|
"description": "read",
|
||||||
|
"media": "video",
|
||||||
|
"session_id": toId + "-" + formId,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
});
|
|
||||||
ws.onclose = function (evt) {
|
|
||||||
console.log(evt);
|
|
||||||
}
|
|
||||||
ws.onmessage = function (evt) {
|
|
||||||
let msg = JSON.parse(evt.data)
|
|
||||||
if (!msg) {
|
|
||||||
return console.log('failed to parse msg')
|
|
||||||
}
|
|
||||||
console.log(msg);
|
|
||||||
|
|
||||||
switch (msg.type) {
|
|
||||||
case 'offer':
|
|
||||||
let offer = msg.data.description
|
|
||||||
pc.setRemoteDescription(offer)
|
|
||||||
pc.createAnswer().then(answer => {
|
|
||||||
pc.setLocalDescription(answer)
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
type: 'answer', data: {
|
|
||||||
'to': msg.data.from,
|
|
||||||
'from': "31283192",
|
|
||||||
'description': { 'sdp': answer.sdp, 'type': answer.type },
|
|
||||||
'session_id': msg.data.from + "-31283192",
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
case 'candidate':
|
|
||||||
let candidate = msg.content.body
|
|
||||||
if (!candidate) {
|
|
||||||
return console.log('failed to parse candidate')
|
|
||||||
}
|
|
||||||
pc.addIceCandidate(candidate)
|
|
||||||
case "answer":
|
case "answer":
|
||||||
pc?.setRemoteDescription(msg.data.description)
|
pc?.setRemoteDescription(msg.content.body.description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +222,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initSocket()
|
initSocket()
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -61,7 +61,7 @@ export type AutoReconnectOptions = boolean | {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public hert(){
|
public hert(){
|
||||||
this.times = setInterval(() => this.send({"type":"heartbeat"}), 3000)
|
this.times = setInterval(() => this.send({"type":"heartbeat","data":{}}), 10000)
|
||||||
}
|
}
|
||||||
private shouldReconnect(): boolean {
|
private shouldReconnect(): boolean {
|
||||||
if (typeof this.autoReconnect === 'boolean') {
|
if (typeof this.autoReconnect === 'boolean') {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
import SocketService from "./socket";
|
import SocketService from "./socket";
|
||||||
|
import baseHttp from "@/service/base";
|
||||||
|
|
||||||
class WebRtc {
|
class WebRtc {
|
||||||
private mediaStream: MediaStream | Blob | null = null;
|
private mediaStream: MediaStream | Blob | null = null;
|
||||||
|
@ -7,167 +8,162 @@ class WebRtc {
|
||||||
private ws: SocketService | null = null;
|
private ws: SocketService | null = null;
|
||||||
private video: HTMLVideoElement | null = null;
|
private video: HTMLVideoElement | null = null;
|
||||||
private userToId: string = "";
|
private userToId: string = "";
|
||||||
open = () => {
|
async init(userId) {
|
||||||
this.ws?.send(JSON.stringify({
|
this.userToId = userId
|
||||||
type: "new", "data": {
|
|
||||||
"name": "admin",
|
|
||||||
"id": "31283192",
|
|
||||||
"user_agent": "flutter-webrtc/js"
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
async init() {
|
|
||||||
this.ws = SocketService.getInstance();
|
this.ws = SocketService.getInstance();
|
||||||
this.ws.on("message", this.onMessage);
|
this.ws.on("message", this.onMessage);
|
||||||
this.createOffer()
|
|
||||||
}
|
}
|
||||||
onMessage = (e: any) => {
|
onMessage = (e: any) => {
|
||||||
let that = this;
|
let msg = JSON.parse(e)
|
||||||
let msg = JSON.parse(e.data)
|
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
return console.log('failed to parse msg')
|
return console.log('failed to parse msg')
|
||||||
}
|
}
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case 'offer':
|
case 'offer':
|
||||||
let offer = msg.data.description
|
let offer = msg.content.body.description;
|
||||||
that.pee?.setRemoteDescription(offer)
|
this.pee?.setRemoteDescription(offer)
|
||||||
that.pee?.createAnswer().then(answer => {
|
this.pee?.createAnswer().then(answer => {
|
||||||
that.pee?.setLocalDescription(answer)
|
this.pee?.setLocalDescription(answer)
|
||||||
that.ws?.send(JSON.stringify({
|
this.ws?.send({
|
||||||
type: 'answer', data: {
|
type: 'answer',
|
||||||
'to': msg.data.from,
|
data: {
|
||||||
'from': "31283192",
|
to: msg.content.body.from,
|
||||||
'description': { 'sdp': answer.sdp, 'type': answer.type },
|
from: "admin",
|
||||||
'session_id': msg.data.from + "-31283192",
|
description: { 'sdp': answer.sdp, 'type': answer.type },
|
||||||
|
session_id: msg.content.body.from + "-admin",
|
||||||
}
|
}
|
||||||
}))
|
|
||||||
})
|
})
|
||||||
return
|
})
|
||||||
|
break;
|
||||||
|
case "read":
|
||||||
|
this.sendOffer()
|
||||||
|
break;
|
||||||
case 'candidate':
|
case 'candidate':
|
||||||
let candidate = msg.data.candidate
|
let candidate = msg.content.body.description
|
||||||
if (!candidate) {
|
if (!candidate) {
|
||||||
return console.log('failed to parse candidate')
|
return console.log('failed to parse candidate')
|
||||||
}
|
}
|
||||||
that.pee?.addIceCandidate(candidate)
|
this.pee?.addIceCandidate(candidate)
|
||||||
break;
|
break;
|
||||||
case "answer":
|
case "answer":
|
||||||
that.pee?.setRemoteDescription(msg.data.description)
|
this.pee?.setRemoteDescription(msg.content.body.description)
|
||||||
break;
|
break;
|
||||||
case "bye":
|
case "bye":
|
||||||
that.pee?.close()
|
this.close()
|
||||||
that.close()
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async createOffer() {
|
async createOffer() {
|
||||||
var url =
|
let basData =await baseHttp.get('/public/webRtcConfig', { service: "11", username: "admin" })
|
||||||
'http://rw.quwanya.cn:12217/api/turn?service=turn&username=flutter-webrtc';
|
|
||||||
fetch(url)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
const configuration = {
|
const configuration = {
|
||||||
iceServers: [
|
iceServers: [
|
||||||
{
|
{
|
||||||
urls: data.uris[0],
|
urls: basData.data.credential.uris,
|
||||||
"username": data.username,
|
username: basData.data.credential.username,
|
||||||
"credential": data.password
|
credential: basData.data.credential.password,
|
||||||
|
ttl:basData.data.credential.ttl
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
this.gets(configuration)
|
this.gets(configuration)
|
||||||
})
|
|
||||||
try {
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async gets(configuration) {
|
async gets(configuration) {
|
||||||
console.log(configuration);
|
this.pee = new RTCPeerConnection(configuration);
|
||||||
const peerConnection = new RTCPeerConnection(configuration);
|
|
||||||
this.pee = peerConnection
|
|
||||||
// 获取远方流添加到页面播放
|
// 获取远方流添加到页面播放
|
||||||
peerConnection.ontrack = event => {
|
this.pee.ontrack = event => {
|
||||||
const remoteVideo = document.querySelector('#remoteVideo') as HTMLVideoElement;
|
const re = document.querySelector('#remoteVideo') as HTMLVideoElement;
|
||||||
remoteVideo.autoplay = true
|
re.autoplay = true
|
||||||
remoteVideo.controls = true
|
re.controls = true
|
||||||
remoteVideo.srcObject = event.streams[0];
|
console.log(event.streams[0])
|
||||||
console.log(event);
|
re.srcObject = event.streams[0];
|
||||||
|
event.track.onmute = function (event) {
|
||||||
event.track.onmute = function () {
|
re.play()
|
||||||
remoteVideo.play()
|
}
|
||||||
|
event.streams[0].onremovetrack = ({ track }) => {
|
||||||
|
if (re.parentNode) {
|
||||||
|
re.parentNode.removeChild(re)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await this.getMedia(peerConnection)
|
this.pee.onicecandidate = e => {
|
||||||
|
|
||||||
peerConnection.onicecandidate = e => {
|
|
||||||
if (!e.candidate) {
|
if (!e.candidate) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.ws?.send(JSON.stringify({ type: 'candidate', data: e }))
|
this.ws?.send({
|
||||||
|
type: "candidate", data: {
|
||||||
|
to: this.userToId,
|
||||||
|
from: "admin",
|
||||||
|
description: e.candidate,
|
||||||
|
media: "video",
|
||||||
|
session_id: this.userToId + "-admin",
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
sendOffer(userId) {
|
this.ws?.send({
|
||||||
|
type: "call",
|
||||||
|
data: {
|
||||||
|
to: this.userToId,
|
||||||
|
from: "admin",
|
||||||
|
description: "call",
|
||||||
|
media: "video",
|
||||||
|
session_id: this.userToId + "-admin",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sendOffer() {
|
||||||
let that = this;
|
let that = this;
|
||||||
that.userToId = userId;
|
|
||||||
that.video = document.getElementById('rtcVideo') as HTMLVideoElement;
|
|
||||||
if (that.pee?.connectionState === "closed") {
|
|
||||||
that.createOffer()
|
|
||||||
}
|
|
||||||
that.pee?.createOffer().then(function (offer) {
|
that.pee?.createOffer().then(function (offer) {
|
||||||
that.pee?.setLocalDescription(offer);
|
that.pee?.setLocalDescription(offer);
|
||||||
that.ws?.send(JSON.stringify({
|
that.ws?.send({
|
||||||
type: "offer", "data": {
|
type: "offer",
|
||||||
"to": userId,
|
data: {
|
||||||
"from": "31283192",
|
to: that.userToId,
|
||||||
"description": offer,
|
from: "admin",
|
||||||
"media": "video",
|
description: offer,
|
||||||
"session_id": userId + "-31283192",
|
media: "video",
|
||||||
|
session_id: that.userToId + "-admin",
|
||||||
}
|
}
|
||||||
}))
|
})
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
// 错误处理
|
// 错误处理
|
||||||
console.error(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
addIceCandidate(candidate) {
|
async getMedia() {
|
||||||
this.pee?.addIceCandidate(candidate)
|
|
||||||
}
|
|
||||||
async getMedia(pee: RTCPeerConnection) {
|
|
||||||
try {
|
try {
|
||||||
|
this.video = document.getElementById('rtcVideo') as HTMLVideoElement;
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
video: true,
|
video: true,
|
||||||
audio: true
|
audio: true
|
||||||
});
|
});
|
||||||
this.mediaStream = stream;
|
this.mediaStream = stream;
|
||||||
stream.getTracks().forEach(track => pee.addTrack(track, stream))
|
stream.getTracks().forEach(track => this.pee?.addTrack(track, stream))
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
calls(userId) {
|
|
||||||
this.sendOffer(userId)
|
|
||||||
if (this.video) {
|
if (this.video) {
|
||||||
this.video.srcObject = this.mediaStream;
|
this.video.srcObject = this.mediaStream;
|
||||||
this.video.autoplay = true;
|
this.video.autoplay = true;
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async calls() {
|
||||||
|
await this.createOffer()
|
||||||
|
await this.getMedia()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.video?.pause();
|
this.video?.pause();
|
||||||
this.pee?.close();
|
this.pee?.close();
|
||||||
this.ws?.send(JSON.stringify({
|
// this.ws?.send({
|
||||||
"type": "bye", "data": {
|
// type: "bye",
|
||||||
"session_id": this.userToId + "31283192",
|
// data: {
|
||||||
"to": this.userToId
|
// session_id: this.userToId + "admin",
|
||||||
}
|
// to: this.userToId,
|
||||||
}
|
// from: "admin"
|
||||||
));
|
// }
|
||||||
|
// });
|
||||||
(this.mediaStream as MediaStream)?.getTracks().forEach(track => track.stop());
|
(this.mediaStream as MediaStream)?.getTracks().forEach(track => track.stop());
|
||||||
this.ws?.close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue