|
|
@@ -1,44 +1,68 @@
|
|
|
import { parseQuery } from "./utils"
|
|
|
import { IRequestLanguages } from "../types"
|
|
|
+import { agoraClient } from "@/client/api"
|
|
|
|
|
|
const MODE = import.meta.env.MODE
|
|
|
let gatewayAddress = "https://api.agora.io"
|
|
|
-const BASE_URL = "https://service.agora.io/toolbox-overseas"
|
|
|
|
|
|
// ---------------------------------------
|
|
|
-const appId = import.meta.env.VITE_AGORA_APP_ID
|
|
|
-const appCertificate = import.meta.env.VITE_AGORA_APP_CERTIFICATE
|
|
|
const SUB_BOT_UID = "1000"
|
|
|
const PUB_BOT_UID = "2000"
|
|
|
|
|
|
let agoraToken = ""
|
|
|
let genTokenTime = 0
|
|
|
+let agoraConfig: {
|
|
|
+ appId: string
|
|
|
+ sttJoinUrl: string
|
|
|
+ sttWsUrl: string
|
|
|
+ defaultChannel: string
|
|
|
+} | null = null
|
|
|
|
|
|
export async function apiGetAgoraToken(config: { uid: string | number; channel: string }) {
|
|
|
- if (!appCertificate) {
|
|
|
- return null
|
|
|
+ try {
|
|
|
+ // 获取配置和Token
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { uid, channel } = config
|
|
|
+ const response = await agoraClient.token.$get({
|
|
|
+ query: { type: 'rtc', channel, userId: uid.toString() }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('Token获取失败')
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+ return data.token
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取Agora Token失败:', error)
|
|
|
+ throw error
|
|
|
}
|
|
|
- const { uid, channel } = config
|
|
|
- const url = `${BASE_URL}/v2/token/generate`
|
|
|
- const data = {
|
|
|
- appId,
|
|
|
- appCertificate,
|
|
|
- channelName: channel,
|
|
|
- expire: 7200,
|
|
|
- src: "web",
|
|
|
- types: [1, 2],
|
|
|
- uid: uid + "",
|
|
|
+}
|
|
|
+
|
|
|
+export async function fetchAgoraConfig() {
|
|
|
+ try {
|
|
|
+ const response = await agoraClient.token.$get({
|
|
|
+ query: { type: 'rtc', channel: 'default', userId: '0' }
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('配置获取失败')
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+ agoraConfig = {
|
|
|
+ appId: data.appId,
|
|
|
+ sttJoinUrl: data.sttJoinUrl,
|
|
|
+ sttWsUrl: data.sttWsUrl,
|
|
|
+ defaultChannel: data.defaultChannel
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取Agora配置失败:', error)
|
|
|
+ throw error
|
|
|
}
|
|
|
- let resp = await fetch(url, {
|
|
|
- method: "POST",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- },
|
|
|
- body: JSON.stringify(data),
|
|
|
- })
|
|
|
- resp = (await resp.json()) || {}
|
|
|
- // @ts-ignore
|
|
|
- return resp?.data?.token || ""
|
|
|
}
|
|
|
|
|
|
const genAuthorization = async (config: { uid: string | number; channel: string }) => {
|
|
|
@@ -58,40 +82,50 @@ export const apiSTTAcquireToken = async (options: {
|
|
|
channel: string
|
|
|
uid: string | number
|
|
|
}): Promise<any> => {
|
|
|
- const { channel } = options
|
|
|
- const data: any = {
|
|
|
- instanceId: channel,
|
|
|
- }
|
|
|
- if (MODE == "test") {
|
|
|
- data.testIp = "218.205.37.49"
|
|
|
- data.testPort = 4447
|
|
|
- const queryParams = parseQuery(window.location.href)
|
|
|
- const denoise = queryParams?.denoise
|
|
|
- if (denoise == "true") {
|
|
|
- gatewayAddress = "https://service-staging.agora.io/speech-to-text-filter"
|
|
|
- data.testIp = "183.131.160.168"
|
|
|
- } else if (denoise == "false") {
|
|
|
- gatewayAddress = "https://service-staging.agora.io/speech-to-text"
|
|
|
- data.testIp = "114.236.138.39"
|
|
|
+ try {
|
|
|
+ // 获取配置
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
}
|
|
|
- }
|
|
|
- const url = `${gatewayAddress}/v1/projects/${appId}/rtsc/speech-to-text/builderTokens`
|
|
|
- let res = await fetch(url, {
|
|
|
- method: "POST",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- Authorization: await genAuthorization(options),
|
|
|
- },
|
|
|
- body: JSON.stringify(data),
|
|
|
- })
|
|
|
- if (res.status == 200) {
|
|
|
- res = await res.json()
|
|
|
- return res
|
|
|
- } else {
|
|
|
- // status: 504
|
|
|
- // please enable the realtime transcription service for this appid
|
|
|
- console.error(res.status, res)
|
|
|
- throw new Error(res.toString())
|
|
|
+
|
|
|
+ const { channel } = options
|
|
|
+ const data: any = {
|
|
|
+ instanceId: channel,
|
|
|
+ }
|
|
|
+ if (MODE == "test") {
|
|
|
+ data.testIp = "218.205.37.49"
|
|
|
+ data.testPort = 4447
|
|
|
+ const queryParams = parseQuery(window.location.href)
|
|
|
+ const denoise = queryParams?.denoise
|
|
|
+ if (denoise == "true") {
|
|
|
+ gatewayAddress = "https://service-staging.agora.io/speech-to-text-filter"
|
|
|
+ data.testIp = "183.131.160.168"
|
|
|
+ } else if (denoise == "false") {
|
|
|
+ gatewayAddress = "https://service-staging.agora.io/speech-to-text"
|
|
|
+ data.testIp = "114.236.138.39"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const url = `${gatewayAddress}/v1/projects/${agoraConfig!.appId}/rtsc/speech-to-text/builderTokens`
|
|
|
+ let res = await fetch(url, {
|
|
|
+ method: "POST",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ Authorization: await genAuthorization(options),
|
|
|
+ },
|
|
|
+ body: JSON.stringify(data),
|
|
|
+ })
|
|
|
+ if (res.status == 200) {
|
|
|
+ res = await res.json()
|
|
|
+ return res
|
|
|
+ } else {
|
|
|
+ // status: 504
|
|
|
+ // please enable the realtime transcription service for this appid
|
|
|
+ console.error(res.status, res)
|
|
|
+ throw new Error(res.toString())
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('STT Token获取失败:', error)
|
|
|
+ throw error
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -101,12 +135,19 @@ export const apiSTTStartTranscription = async (options: {
|
|
|
languages: IRequestLanguages[]
|
|
|
token: string
|
|
|
}): Promise<{ taskId: string }> => {
|
|
|
- const { channel, languages, token, uid } = options
|
|
|
- const url = `${gatewayAddress}/v1/projects/${appId}/rtsc/speech-to-text/tasks?builderToken=${token}`
|
|
|
- let subBotToken = null
|
|
|
- let pubBotToken = null
|
|
|
- if (appCertificate) {
|
|
|
- const data = await Promise.all([
|
|
|
+ try {
|
|
|
+ // 获取配置
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { channel, languages, token, uid } = options
|
|
|
+ const url = `${gatewayAddress}/v1/projects/${agoraConfig!.appId}/rtsc/speech-to-text/tasks?builderToken=${token}`
|
|
|
+ let subBotToken = null
|
|
|
+ let pubBotToken = null
|
|
|
+
|
|
|
+ // 获取Bot Token
|
|
|
+ const tokenData = await Promise.all([
|
|
|
apiGetAgoraToken({
|
|
|
uid: SUB_BOT_UID,
|
|
|
channel,
|
|
|
@@ -116,44 +157,48 @@ export const apiSTTStartTranscription = async (options: {
|
|
|
channel,
|
|
|
}),
|
|
|
])
|
|
|
- subBotToken = data[0]
|
|
|
- pubBotToken = data[1]
|
|
|
- }
|
|
|
- const body: any = {
|
|
|
- languages: languages.map((item) => item.source),
|
|
|
- maxIdleTime: 60,
|
|
|
- rtcConfig: {
|
|
|
- channelName: channel,
|
|
|
- subBotUid: SUB_BOT_UID,
|
|
|
- pubBotUid: PUB_BOT_UID,
|
|
|
- },
|
|
|
- }
|
|
|
- if (subBotToken && pubBotToken) {
|
|
|
- body.rtcConfig.subBotToken = subBotToken
|
|
|
- body.rtcConfig.pubBotToken = pubBotToken
|
|
|
- }
|
|
|
- if (languages.find((item) => item.target.length)) {
|
|
|
- body.translateConfig = {
|
|
|
- forceTranslateInterval: 2,
|
|
|
- languages: languages.filter((item) => item.target.length),
|
|
|
+ subBotToken = tokenData[0]
|
|
|
+ pubBotToken = tokenData[1]
|
|
|
+
|
|
|
+ const body: any = {
|
|
|
+ languages: languages.map((item) => item.source),
|
|
|
+ maxIdleTime: 60,
|
|
|
+ rtcConfig: {
|
|
|
+ channelName: channel,
|
|
|
+ subBotUid: SUB_BOT_UID,
|
|
|
+ pubBotUid: PUB_BOT_UID,
|
|
|
+ },
|
|
|
}
|
|
|
+ if (subBotToken && pubBotToken) {
|
|
|
+ body.rtcConfig.subBotToken = subBotToken
|
|
|
+ body.rtcConfig.pubBotToken = pubBotToken
|
|
|
+ }
|
|
|
+ if (languages.find((item) => item.target.length)) {
|
|
|
+ body.translateConfig = {
|
|
|
+ forceTranslateInterval: 2,
|
|
|
+ languages: languages.filter((item) => item.target.length),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const res = await fetch(url, {
|
|
|
+ method: "POST",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ Authorization: await genAuthorization({
|
|
|
+ uid,
|
|
|
+ channel,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ body: JSON.stringify(body),
|
|
|
+ })
|
|
|
+ const responseData = await res.json()
|
|
|
+ if (res.status !== 200) {
|
|
|
+ throw new Error((responseData as any)?.message || "start transcription failed")
|
|
|
+ }
|
|
|
+ return responseData as { taskId: string }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('STT转录启动失败:', error)
|
|
|
+ throw error
|
|
|
}
|
|
|
- const res = await fetch(url, {
|
|
|
- method: "POST",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- Authorization: await genAuthorization({
|
|
|
- uid,
|
|
|
- channel,
|
|
|
- }),
|
|
|
- },
|
|
|
- body: JSON.stringify(body),
|
|
|
- })
|
|
|
- const data = await res.json()
|
|
|
- if (res.status !== 200) {
|
|
|
- throw new Error(data?.message || "start transcription failed")
|
|
|
- }
|
|
|
- return data
|
|
|
}
|
|
|
|
|
|
export const apiSTTStopTranscription = async (options: {
|
|
|
@@ -162,18 +207,28 @@ export const apiSTTStopTranscription = async (options: {
|
|
|
uid: number | string
|
|
|
channel: string
|
|
|
}) => {
|
|
|
- const { taskId, token, uid, channel } = options
|
|
|
- const url = `${gatewayAddress}/v1/projects/${appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}`
|
|
|
- await fetch(url, {
|
|
|
- method: "DELETE",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- Authorization: await genAuthorization({
|
|
|
- uid,
|
|
|
- channel,
|
|
|
- }),
|
|
|
- },
|
|
|
- })
|
|
|
+ try {
|
|
|
+ // 获取配置
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { taskId, token, uid, channel } = options
|
|
|
+ const url = `${gatewayAddress}/v1/projects/${agoraConfig!.appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}`
|
|
|
+ await fetch(url, {
|
|
|
+ method: "DELETE",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ Authorization: await genAuthorization({
|
|
|
+ uid,
|
|
|
+ channel,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('STT转录停止失败:', error)
|
|
|
+ throw error
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
export const apiSTTQueryTranscription = async (options: {
|
|
|
@@ -182,19 +237,29 @@ export const apiSTTQueryTranscription = async (options: {
|
|
|
uid: number | string
|
|
|
channel: string
|
|
|
}) => {
|
|
|
- const { taskId, token, uid, channel } = options
|
|
|
- const url = `${gatewayAddress}/v1/projects/${appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}`
|
|
|
- const res = await fetch(url, {
|
|
|
- method: "GET",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- Authorization: await genAuthorization({
|
|
|
- uid,
|
|
|
- channel,
|
|
|
- }),
|
|
|
- },
|
|
|
- })
|
|
|
- return await res.json()
|
|
|
+ try {
|
|
|
+ // 获取配置
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { taskId, token, uid, channel } = options
|
|
|
+ const url = `${gatewayAddress}/v1/projects/${agoraConfig!.appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}`
|
|
|
+ const res = await fetch(url, {
|
|
|
+ method: "GET",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ Authorization: await genAuthorization({
|
|
|
+ uid,
|
|
|
+ channel,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ })
|
|
|
+ return await res.json()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('STT转录查询失败:', error)
|
|
|
+ throw error
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
export const apiSTTUpdateTranscription = async (options: {
|
|
|
@@ -205,24 +270,34 @@ export const apiSTTUpdateTranscription = async (options: {
|
|
|
updateMaskList: string[]
|
|
|
data: any
|
|
|
}) => {
|
|
|
- const { taskId, token, uid, channel, data, updateMaskList } = options
|
|
|
- const updateMask = updateMaskList.join(",")
|
|
|
- const url = `${gatewayAddress}/v1/projects/${appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}&sequenceId=1&updateMask=${updateMask}`
|
|
|
- const body: any = {
|
|
|
- ...data,
|
|
|
+ try {
|
|
|
+ // 获取配置
|
|
|
+ if (!agoraConfig) {
|
|
|
+ await fetchAgoraConfig()
|
|
|
+ }
|
|
|
+
|
|
|
+ const { taskId, token, uid, channel, data, updateMaskList } = options
|
|
|
+ const updateMask = updateMaskList.join(",")
|
|
|
+ const url = `${gatewayAddress}/v1/projects/${agoraConfig!.appId}/rtsc/speech-to-text/tasks/${taskId}?builderToken=${token}&sequenceId=1&updateMask=${updateMask}`
|
|
|
+ const body: any = {
|
|
|
+ ...data,
|
|
|
+ }
|
|
|
+ const res = await fetch(url, {
|
|
|
+ method: "PATCH",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ Authorization: await genAuthorization({
|
|
|
+ uid,
|
|
|
+ channel,
|
|
|
+ }),
|
|
|
+ },
|
|
|
+ body: JSON.stringify(body),
|
|
|
+ })
|
|
|
+ return await res.json()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('STT转录更新失败:', error)
|
|
|
+ throw error
|
|
|
}
|
|
|
- const res = await fetch(url, {
|
|
|
- method: "PATCH",
|
|
|
- headers: {
|
|
|
- "Content-Type": "application/json",
|
|
|
- Authorization: await genAuthorization({
|
|
|
- uid,
|
|
|
- channel,
|
|
|
- }),
|
|
|
- },
|
|
|
- body: JSON.stringify(body),
|
|
|
- })
|
|
|
- return await res.json()
|
|
|
}
|
|
|
|
|
|
// --------------- gpt ----------------
|