Commit 83ceae1a authored by ali's avatar ali

feat: 照片数字人直播切换到sdk 接口方案

parent d32e1cdc
......@@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"axios": "^1.6.2",
"crypto-js": "^4.1.1",
"electron-store": "^8.1.0",
"EventEmitter": "^1.0.0",
"flv.js": "^1.6.2",
......@@ -3911,6 +3912,11 @@
"node": ">= 8"
}
},
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"node_modules/css": {
"version": "2.2.4",
"resolved": "https://registry.npmmirror.com/css/-/css-2.2.4.tgz",
......
......@@ -41,7 +41,8 @@
"vue": "^3.3.7",
"vue-i18n": "^9.6.2",
"vue-router": "^4.2.5",
"vuetify": "^3.3.23"
"vuetify": "^3.3.23",
"crypto-js": "^4.1.1"
},
"devDependencies": {
"@mdi/font": "^7.3.67",
......@@ -75,4 +76,4 @@
"vue-tsc": "^1.8.22",
"xvfb-maybe": "^0.2.1"
}
}
}
\ No newline at end of file
......@@ -64,10 +64,11 @@ const asrItems = ref([
// 'Whisper Api'
])
const liveHosts = ref([
'http://111.229.216.162:9000',
'http://124.221.182.173:9000',
'http://110.42.214.59:9000',
'http://122.51.32.12:9000'
'laihua',
// 'http://111.229.216.162:9000',
// 'http://124.221.182.173:9000',
// 'http://110.42.214.59:9000',
// 'http://122.51.32.12:9000'
])
const asrSelect = ref(setting.asr)
......
/* eslint-disable camelcase */
import http from '@/renderer/utils/http'
import http, { axiosInstance } from '@/renderer/utils/http'
import { JWT } from '@/renderer/utils/jwt';
import { HwWebRTC } from './HwWebRTC'
import { guid } from '@/renderer/utils/index'
import EventEmitter from 'EventEmitter'
......@@ -11,14 +12,20 @@ type LiveOptions = {
audioUrl?: string | null
taskId: string
imgUrl: string
pushUrl: string
pullUrl: string
pushUrl?: string
pullUrl?: string
speed?: number
bitrate: number
superres: boolean
isLast: boolean
}
type SdkConfigDataParams = {
baseUrl: string;
baseSocketUrl: string;
};
export class PhotoAnswer {
question = ''
answer = ''
......@@ -65,7 +72,7 @@ export type PhotoEventTypeFn<T extends PhotoEventType> = {
}[T]
export class PhotoRole extends EventEmitter {
readonly host: string
private host: string
readonly view: HTMLCanvasElement
readonly ctx: CanvasRenderingContext2D
private _webRTCContainer: HTMLDivElement = document.createElement('div')
......@@ -109,10 +116,10 @@ export class PhotoRole extends EventEmitter {
this._liveTaskQueue.push({
imgUrl: this.url,
taskId,
pushUrl: `rtmp://push.laihua.com/web/${taskId}`,
pullUrl: `webrtc://pull.laihua.com/web/${taskId}`,
speaker: 'speaker',
languageCode: 'zh-CN',
// pushUrl: `rtmp://push.laihua.com/web/${taskId}`,
// pullUrl: `webrtc://pull.laihua.com/web/${taskId}`,
speaker: '101015',
languageCode: 'zh_cn',
audioUrl,
speed: 10,
bitrate: 2000,
......@@ -224,7 +231,7 @@ export class PhotoRole extends EventEmitter {
const resp = (await http({
method: 'POST',
url: `${this.host}/create`,
url: `${this.host}/live`,
data: { ...options } // ip: 'http://116.63.168.14:9000'
})) as {
code: number
......@@ -254,7 +261,7 @@ export class PhotoRole extends EventEmitter {
private async _appendLive(options: LiveOptions) {
const resp = (await http({
method: 'POST',
url: `${this.host}/append`,
url: `${this.host}/live/append`,
data: { ...options } // ip: 'http://116.63.168.14:9000'
})) as {
code: number
......@@ -284,7 +291,7 @@ export class PhotoRole extends EventEmitter {
private async _pushLive(taskId: string) {
const resp = (await http({
method: 'POST',
url: `${this.host}/push`,
url: `${this.host}/live/push`,
data: { taskId }
})) as {
code: number
......@@ -302,7 +309,7 @@ export class PhotoRole extends EventEmitter {
private async _getLiveStatus(taskId: string) {
const resp = (await http({
method: 'GET',
url: `${this.host}/status`,
url: `${this.host}/live/validateStatus`,
params: { taskId }
})) as {
code: number
......@@ -355,20 +362,20 @@ export class PhotoRole extends EventEmitter {
async initLive() {
console.time('init')
console.time('init-_createLive')
console.time('_createLive')
const { pullUrl, taskId, imgInfo } = await this._createLive({
imgUrl: this.url,
pushUrl: `rtmp://push.laihua.com/web/${this.sessionId}`,
pullUrl: `webrtc://pull.laihua.com/web/${this.sessionId}`,
// pushUrl: `rtmp://push.laihua.com/web/${this.sessionId}`,
// pullUrl: `webrtc://pull.laihua.com/web/${this.sessionId}`,
taskId: this.sessionId,
speaker: 'speaker',
languageCode: 'zh-CN',
speaker: '101015',
languageCode: 'zh_cn',
audioUrl: '',
bitrate: 2000,
superres: false,
isLast: true
})
console.timeEnd('init-_createLive')
console.timeEnd('_createLive')
this._rtcVideoInfo = imgInfo
console.time('play')
......@@ -454,10 +461,33 @@ export class PhotoRole extends EventEmitter {
this._rtc = new HwWebRTC(this._webRTCContainer.id)
this._bindEvents()
if (this.host === 'laihua') {
this.host = await this.auth();
}
await this.initLive()
// this._pollStatus(this.sessionId);
}
async auth() {
const token = JWT.encode(
JSON.stringify({ appId: '88ca56ac88257f14', iat: new Date().getTime() + 1000 * 30 }),
'92b39dd13b952bcd4ce1995473cc3302'
);
axiosInstance.defaults.headers.common.Authorization = `Bearer ${token}`;
const res = await http({ url: 'https://openapi.laihua.com/sdk/getConfig' });
const { code, data } = res as {
code: number | string;
data: SdkConfigDataParams | string;
};
if (code !== 200) {
throw new Error(`${code}: ${ JSON.stringify(res) }`);
}
return (data as SdkConfigDataParams).baseUrl;
}
destroy() {
this._webRTCContainer && document.body.removeChild(this._webRTCContainer)
this._rtc?.stopPlay()
......
......@@ -66,7 +66,7 @@ const useSettingsStore = defineStore('settings', {
llmUrl: 'ws://127.0.0.1:9899/api/v1/stream',
llmToTTSSliceLength: 20,
voskWsLUrl: 'ws://127.0.0.1:2700',
liveHost: 'http://122.51.32.12:9000',
liveHost: 'laihua',
vConsole: true
}) as ISettings,
getters: {},
......
import CryptoJS from 'crypto-js';
export class JWT {
static sign(content: string, secret: string) {
const r = CryptoJS.HmacSHA256(content, secret);
const b = CryptoJS.enc.Base64.stringify(r);
return this.base64urlEscape(b);
}
static base64urlEscape(str: string) {
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
static toBase64(content: string) {
return btoa(content);
}
static encode(username: string, secret: string) {
const header = this.toBase64(JSON.stringify({ typ: 'JWT', alg: 'HS256' }));
const content = this.toBase64(username);
const sign = this.sign([header, content].join('.'), secret);
return [header, content, sign].join('.');
}
static decode(token: string, secret: string) {
const [header, content, sign] = token.split('.');
const newSign = this.sign([header, content].join('.'), secret);
if (sign === newSign) {
return atob(content);
} else {
throw new Error('被篡改');
}
}
}
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