直播插件

main
刘妍 2 months ago
parent 752c869865
commit bdd8aef058

@ -0,0 +1,14 @@
import { defHttp } from '@/utils/http/axios';
enum Api {
VerifyToken = '/api/DroneDock/VerifyToken',
GetDroneDockflightInfos = '/api/DroneDock/GetDroneDockflightInfos',
}
export function getVerifyToken(token) {
return defHttp.get({ url: Api.VerifyToken + '?token=' + token });
}
export function getDroneDockflightInfos(id) {
return defHttp.get({ url: Api.GetDroneDockflightInfos + '?taskid=' + id });
}

@ -0,0 +1,238 @@
import { createConnection, client, servicesTopic, destroyConnection } from './src/mqtt';
import { airport, uav, liveInfo, buildGUID } from './src/config';
import { GetUavPageByDocksn } from '@/api/demo/projecthome';
import { getVerifyToken, getDroneDockflightInfos } from '@/api/workmanagement/droneDock';
import TCPlayer from 'tcplayer.js';
const bid = buildGUID();
let video_id;
let sn;
let live_url;
class LiveStreamPlugin {
constructor() {
console.log('LiveStreamPlugin constructor');
}
initSDK(token: String) {
/**
* SDKtokenak/sktoken
* 使
*/
return getVerifyToken(token).then((res) => {
return res;
});
}
setLiveStreamControl(divContainor: HTMLElement, deviceType: number) {
/**
*
* divContainordiv
* deviceType 0 1
*/
console.log('LiveStreamPlugin setLiveStreamControl', divContainor, deviceType);
divContainor.innerHTML =
' <video id="player-container-id" preload="auto" playsinline webkit-playsinline > </video>';
setTimeout(() => {
const player = TCPlayer('player-container-id', {
sources: [
{
src: live_url + '.flv', // 播放地址
},
],
licenseUrl: live_url + '.flv', // license 地址,必传。参考准备工作部分,在视立方控制台申请 license 后可获得 licenseUrl
autoplay: true, // 是否自动播放
});
}, 1000);
}
async startLiveStreamCall(serialNum: String, deviceType: number) {
/**
*
* serialNum
* deviceType 0 1
*/
console.log('LiveStreamPlugin startLiveStreamCall', serialNum, deviceType);
sn = serialNum;
createConnection('mqtt_' + serialNum);
video_id =
deviceType == 1
? serialNum + '/' + airport.camera_index + '/' + airport.video_index
: serialNum + '/' + uav.camera_index + '/' + uav.video_index;
// const liveUrl = liveInfo.rtmp + serialNum;
let querys;
if (deviceType == 1) {
querys = {
bid: bid,
method: 'live_start_push',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
url_type: 1,
url: liveInfo.rtmp + '5',
video_id: video_id,
video_quality: 3,
},
};
live_url = liveInfo.url + '5';
} else {
// 根据机场sn获取无人机sn
const params = {
sn: sn,
page: 1,
limit: 99,
};
await GetUavPageByDocksn(params).then((res) => {
console.log('GetUavPageByDocksn', res);
if (res.items.length > 0) {
querys = {
bid: bid,
method: 'live_start_push',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
url_type: 1,
url: liveInfo.rtmp + '6',
video_id: video_id,
video_quality: 3,
},
};
}
});
live_url = liveInfo.url + '5';
}
// 发送消息
servicesTopic(serialNum, querys);
// 订阅回执
client.subscribe('thing/product/' + serialNum + '/services_reply', { qos: 0 }, () => {});
// 接收消息
client.on('message', (topic, message) => {
const rs = JSON.parse(message);
if (rs.bid == bid) {
console.log(rs);
console.log('LiveStreamPlugin liveStartPush', rs);
}
});
}
endLiveStreamCall(deviceType: number) {
/**
*
* deviceType 0 1
*/
console.log('LiveStreamPlugin endLiveStreamCall', deviceType);
const querys = {
bid: bid,
method: 'live_stop_push',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
video_id: video_id,
},
};
servicesTopic(sn, querys);
}
takePicture(callback) {
/**
*
* callback
* issuccess
* true/false
* imgBlobBlob
* zpkzxx
*/
console.log('LiveStreamPlugin takePicture', callback);
servicesTopic(sn, {
bid: bid,
method: 'camera_photo_take',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
const data = {};
callback(data);
}
startVideoRecording() {
/**
*
*/
console.log('LiveStreamPlugin startVideoRecording');
servicesTopic(sn, {
bid: bid,
method: 'payload_authority_grab',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
servicesTopic(sn, {
bid: bid,
method: 'camera_recording_start',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
}
endVideoRecording(callback: Function) {
/**
*
* callback
* issuccess
* true/false
*/
console.log('LiveStreamPlugin endVideoRecording', callback);
servicesTopic(sn, {
bid: bid,
method: 'camera_recording_stop',
tid: buildGUID(),
timestamp: new Date().getTime(),
data: {
payload_index: uav.camera_index,
},
});
const data = {};
callback(data);
}
disposeSDK() {
/**
* SDK
*/
console.log('LiveStreamPlugin disposeSDK');
destroyConnection();
}
async getFlightTaskInfo(serialNum: String) {
/**
*
* serialNum
* FlightTaskInfo
*/
console.log('LiveStreamPlugin getFlightTaskInfo', serialNum);
client.subscribe('thing/product/' + serialNum + '/events', { qos: 2 }, () => {});
// 接收消息
let id = '';
client.on('message', async (topic, message) => {
const rs = JSON.parse(message);
if (
rs.method == 'flighttask_progress' &&
rs.data.output.status == 'in_progress' &&
id == ''
) {
console.log(rs);
id = rs.data.output.ext.flight_id;
return new Promise((resolve, reject) => {
getDroneDockflightInfos(id).then((res) => {
console.log(res);
resolve(res);
});
});
return await getDroneDockflightInfos(id).then((res) => {
return res;
});
}
});
}
}
export default LiveStreamPlugin;

@ -0,0 +1,31 @@
export const airport = {
camera_index: '165-0-7',
video_index: 'normal-0',
};
export const uav = {
camera_index: '99-0-0',
video_index: 'normal-0',
};
export const liveInfo = {
rtmp: 'rtmp://box.wisestcity.com:1935/live/',
url: 'http://box.wisestcity.com:8081/live/',
};
const hexList: string[] = [];
for (let i = 0; i <= 15; i++) {
hexList[i] = i.toString(16);
}
export function buildGUID(): string {
let guid = '';
for (let i = 1; i <= 36; i++) {
if (i === 9 || i === 14 || i === 19 || i === 24) {
guid += '-';
} else if (i === 15) {
guid += 4;
} else if (i === 20) {
guid += hexList[(Math.random() * 4) | 8];
} else {
guid += hexList[(Math.random() * 16) | 0];
}
}
return guid;
}

@ -0,0 +1,70 @@
import mqtt from 'mqtt';
const connection = {
protocol: 'ws',
host: '175.27.168.120',
port: 6010,
endpoint: '/mqtt',
clean: true,
connectTimeout: 30 * 1000, // ms
reconnectPeriod: 4000, // ms
clientId: '',
username: 'sdhc',
password: '',
};
let client: any = {
connected: false,
};
// 创建连接函数
const createConnection = (id, callback?) => {
try {
connection.clientId = id;
const { protocol, host, port, endpoint, ...options } = connection;
const connectUrl = `${protocol}://${host}:${port}${endpoint}`;
client = mqtt.connect(connectUrl, options);
client.on('connect', () => {
if (callback) {
callback();
}
});
} catch (error) {
console.log('mqtt.connect error', error);
}
};
// 断开连接
const destroyConnection = () => {
if (client.connected) {
try {
client.end(false, () => {
client = {
connected: false,
};
console.log('Successfully disconnected!');
});
} catch (error) {
console.log('Disconnect failed', error.toString());
}
}
};
// 订阅事件
const clientSubscribe = (topic: string) => {
client.subscribe(topic, { qos: 0 }, () => {});
};
// 发送消息
// 定义一个函数clientPublish用于发布消息
const clientPublish = (topic: string, querys: any) => {
client.publish(topic, JSON.stringify(querys), { qos: 0 }, (err) => {
if (err) {
console.error('Publish error:', err);
}
});
};
// 发送消息
export const servicesTopic = (id, data) => {
console.log(id, data);
// 发送消息
clientPublish('thing/product/' + id + '/services', data);
};
export { createConnection, client, destroyConnection };

@ -0,0 +1,50 @@
<template>
<div>
<a-button @click="starAirpot"></a-button>
<a-button @click="startUAV"></a-button>
<a-button @click="startRecording"></a-button>
<a-button @click="endRecording"></a-button>
<a-button @click="liveStreamPlugin.disposeSDK"></a-button>
<a-button @click="getTask">线</a-button>
<a-button @click="viewLive"></a-button>
<div id="live-div"> </div>
</div>
</template>
<script setup lang="ts">
import LiveStreamPlugin from '@/plugin/video/index';
import { onMounted } from 'vue';
const liveStreamPlugin = new LiveStreamPlugin();
const starAirpot = () => {
liveStreamPlugin.startLiveStreamCall('8UUXN5400A079H', 1);
};
const startUAV = () => {
liveStreamPlugin.startLiveStreamCall('1581F8HGX254V00A0BUY', 0);
};
const startRecording = () => {
liveStreamPlugin.startVideoRecording();
};
const endRecording = () => {
liveStreamPlugin.endVideoRecording((res) => {
console.log(res);
});
};
const getTask = async () => {
await liveStreamPlugin.getFlightTaskInfo('8UUXN5400A079H').then((res) => {
console.log(res);
});
};
const viewLive = () => {
console.log(document.getElementById('live-div'));
liveStreamPlugin.setLiveStreamControl(document.getElementById('live-div'), '1');
};
onMounted(async () => {
const token =
'API32_HENJOZMPBYKEXNVLFMY3Y5W5SQ.1751622229582.fmCjIucQYyq4YZe4CnSStN/rHcwjZTxUsDuXeXJfrYn0bwoaV1/IW8mcFwtLw8JHjowvMJrmPyy/QZAhssxQCQ==';
const status = await liveStreamPlugin.initSDK(token);
console.log(status);
if (!status) {
console.log('初始化失败');
}
});
</script>
Loading…
Cancel
Save