|
|
@@ -48,10 +48,12 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
channel: string
|
|
|
userName: string
|
|
|
}) {
|
|
|
+ console.debug('[AgoraSTT:STT] Initializing with:', { userId, channel, userName })
|
|
|
this.userId = userId
|
|
|
this.channel = channel
|
|
|
|
|
|
// 加入RTM频道(实时消息)
|
|
|
+ console.debug('[AgoraSTT:STT] Joining RTM channel')
|
|
|
await this.rtmManager.join({
|
|
|
userId: userId + "",
|
|
|
userName,
|
|
|
@@ -59,37 +61,57 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
})
|
|
|
|
|
|
// 加入RTC频道(音频传输)
|
|
|
+ console.debug('[AgoraSTT:STT] Joining RTC channel')
|
|
|
await this.rtcManager.join({
|
|
|
channel,
|
|
|
userId
|
|
|
})
|
|
|
|
|
|
this._init = true
|
|
|
+ console.debug('[AgoraSTT:STT] Initialization completed')
|
|
|
}
|
|
|
|
|
|
async startTranscription(startOptions: STTManagerStartOptions) {
|
|
|
+ console.debug('[AgoraSTT:STT] Starting transcription with options:', startOptions)
|
|
|
if (!this.hasInit) {
|
|
|
throw new Error("please init first")
|
|
|
}
|
|
|
const { languages } = startOptions
|
|
|
if (!languages.length) {
|
|
|
+ console.debug('[AgoraSTT:STT] No languages provided, skipping transcription start')
|
|
|
return
|
|
|
}
|
|
|
// aquire lock
|
|
|
+ console.debug('[AgoraSTT:STT] Acquiring RTM lock')
|
|
|
await this.rtmManager.acquireLock()
|
|
|
try {
|
|
|
+ // 先停止可能存在的旧转录任务
|
|
|
+ if (this.option?.taskId) {
|
|
|
+ console.debug('[AgoraSTT:STT] Stopping existing transcription task:', this.option.taskId)
|
|
|
+ try {
|
|
|
+ await this.stopTranscription()
|
|
|
+ console.debug('[AgoraSTT:STT] Existing transcription stopped successfully')
|
|
|
+ } catch (stopError) {
|
|
|
+ console.warn('[AgoraSTT:STT] Failed to stop existing transcription:', stopError)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// aquire token
|
|
|
+ console.debug('[AgoraSTT:STT] Acquiring STT token')
|
|
|
const data = await apiSTTAcquireToken({
|
|
|
channel: this.channel,
|
|
|
uid: this.userId,
|
|
|
})
|
|
|
const token = data.tokenName
|
|
|
+ console.debug('[AgoraSTT:STT] STT token acquired:', token)
|
|
|
|
|
|
// 创建音频轨道并发布到RTC频道
|
|
|
+ console.debug('[AgoraSTT:STT] Creating and publishing audio tracks')
|
|
|
await this.rtcManager.createTracks()
|
|
|
await this.rtcManager.publish()
|
|
|
|
|
|
// api start
|
|
|
+ console.debug('[AgoraSTT:STT] Starting STT transcription via API')
|
|
|
const res = await apiSTTStartTranscription({
|
|
|
uid: this.userId,
|
|
|
channel: this.channel,
|
|
|
@@ -97,11 +119,13 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
token,
|
|
|
})
|
|
|
const { taskId } = res
|
|
|
+ console.debug('[AgoraSTT:STT] STT transcription started, taskId:', taskId)
|
|
|
this.setOption({
|
|
|
token,
|
|
|
taskId,
|
|
|
})
|
|
|
// set rtm metadata
|
|
|
+ console.debug('[AgoraSTT:STT] Updating RTM metadata')
|
|
|
await Promise.all([
|
|
|
this.rtmManager.updateLanguages(languages),
|
|
|
this.rtmManager.updateSttData({
|
|
|
@@ -112,7 +136,67 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
duration: EXPERIENCE_DURATION,
|
|
|
}),
|
|
|
])
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription start completed successfully')
|
|
|
+
|
|
|
+ // 启动转录状态监控
|
|
|
+ this._startTranscriptionMonitor()
|
|
|
} catch (err) {
|
|
|
+ console.error('[AgoraSTT:STT] Error starting transcription:', err)
|
|
|
+
|
|
|
+ // 如果是409错误(任务已存在),尝试查询任务状态
|
|
|
+ if (err instanceof Error && err.message && err.message.includes('The task has been started')) {
|
|
|
+ console.debug('[AgoraSTT:STT] Task already exists, querying status')
|
|
|
+ console.debug('[AgoraSTT:STT] Error message:', err.message)
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 尝试多种可能的taskId格式
|
|
|
+ let taskIdMatch = err.message.match(/taskId is: ([a-f0-9]+)/)
|
|
|
+ if (!taskIdMatch) {
|
|
|
+ taskIdMatch = err.message.match(/taskId: ([a-f0-9]+)/)
|
|
|
+ }
|
|
|
+ if (!taskIdMatch) {
|
|
|
+ taskIdMatch = err.message.match(/taskId=([a-f0-9]+)/)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 尝试从错误对象的响应数据中提取tokenName
|
|
|
+ let existingToken = ''
|
|
|
+ const anyErr = err as any
|
|
|
+ if (anyErr.responseData && anyErr.responseData.tokenName) {
|
|
|
+ existingToken = anyErr.responseData.tokenName
|
|
|
+ console.debug('[AgoraSTT:STT] Using token from response data:', existingToken)
|
|
|
+ } else {
|
|
|
+ // 如果响应数据中没有tokenName,尝试从错误消息中提取
|
|
|
+ let tokenMatch = err.message.match(/tokenName: ([^,]+)/)
|
|
|
+ if (!tokenMatch) {
|
|
|
+ tokenMatch = err.message.match(/tokenName=([^,]+)/)
|
|
|
+ }
|
|
|
+ existingToken = tokenMatch && tokenMatch[1] ? tokenMatch[1] : this.option?.token || ''
|
|
|
+ console.debug('[AgoraSTT:STT] Using token:', existingToken ? 'extracted from error message' : 'from existing option')
|
|
|
+ }
|
|
|
+
|
|
|
+ if (taskIdMatch && taskIdMatch[1]) {
|
|
|
+ const existingTaskId = taskIdMatch[1]
|
|
|
+
|
|
|
+ console.debug('[AgoraSTT:STT] Found existing taskId:', existingTaskId)
|
|
|
+
|
|
|
+ // 使用现有的taskId和token继续
|
|
|
+ this.setOption({
|
|
|
+ token: existingToken,
|
|
|
+ taskId: existingTaskId,
|
|
|
+ })
|
|
|
+
|
|
|
+ // 启动转录状态监控
|
|
|
+ this._startTranscriptionMonitor()
|
|
|
+ console.debug('[AgoraSTT:STT] Using existing transcription task')
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ console.warn('[AgoraSTT:STT] Could not extract taskId from error message')
|
|
|
+ }
|
|
|
+ } catch (queryError) {
|
|
|
+ console.error('[AgoraSTT:STT] Error handling existing task:', queryError)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
await this.rtmManager.releaseLock()
|
|
|
throw err
|
|
|
}
|
|
|
@@ -120,12 +204,14 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
}
|
|
|
|
|
|
async stopTranscription() {
|
|
|
+ console.debug('[AgoraSTT:STT] Stopping transcription')
|
|
|
if (!this.hasInit) {
|
|
|
throw new Error("please init first")
|
|
|
}
|
|
|
const { taskId, token } = this.option || {}
|
|
|
if (!taskId) {
|
|
|
- throw new Error("taskId is not found")
|
|
|
+ console.debug('[AgoraSTT:STT] No taskId found, nothing to stop')
|
|
|
+ return
|
|
|
}
|
|
|
if (!token) {
|
|
|
throw new Error("token is not found")
|
|
|
@@ -134,21 +220,30 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
await this.rtmManager.acquireLock()
|
|
|
try {
|
|
|
// api stop
|
|
|
+ console.debug('[AgoraSTT:STT] Stopping transcription via API')
|
|
|
await apiSTTStopTranscription({
|
|
|
taskId,
|
|
|
token,
|
|
|
uid: this.userId,
|
|
|
channel: this.channel,
|
|
|
})
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription stopped via API')
|
|
|
|
|
|
// 停止音频轨道
|
|
|
+ console.debug('[AgoraSTT:STT] Unpublishing audio tracks')
|
|
|
await this.rtcManager.unpublish()
|
|
|
|
|
|
// set rtm metadata
|
|
|
+ console.debug('[AgoraSTT:STT] Updating RTM metadata to end status')
|
|
|
await this.rtmManager.updateSttData({
|
|
|
status: "end",
|
|
|
})
|
|
|
+
|
|
|
+ // 清除选项
|
|
|
+ this.removeOption()
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription stopped successfully')
|
|
|
} catch (err) {
|
|
|
+ console.error('[AgoraSTT:STT] Error stopping transcription:', err)
|
|
|
await this.rtmManager.releaseLock()
|
|
|
throw err
|
|
|
}
|
|
|
@@ -156,6 +251,7 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
}
|
|
|
|
|
|
async queryTranscription() {
|
|
|
+ console.debug('[AgoraSTT:STT] Querying transcription status')
|
|
|
const { taskId, token } = this.option || {}
|
|
|
if (!taskId) {
|
|
|
throw new Error("taskId is not found")
|
|
|
@@ -164,12 +260,14 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
throw new Error("token is not found")
|
|
|
}
|
|
|
// api query
|
|
|
- return await apiSTTQueryTranscription({
|
|
|
+ const result = await apiSTTQueryTranscription({
|
|
|
taskId,
|
|
|
token,
|
|
|
uid: this.userId,
|
|
|
channel: this.channel,
|
|
|
})
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription query result:', result)
|
|
|
+ return result
|
|
|
}
|
|
|
|
|
|
async updateTranscription(options: { data: any; updateMaskList: string[] }) {
|
|
|
@@ -219,4 +317,43 @@ export class SttManager extends AGEventEmitter<STTEvents> {
|
|
|
}
|
|
|
|
|
|
// ------------- private -------------
|
|
|
+
|
|
|
+ private _startTranscriptionMonitor() {
|
|
|
+ console.debug('[AgoraSTT:STT] Starting transcription monitor')
|
|
|
+
|
|
|
+ // 定期查询转录状态
|
|
|
+ const monitorInterval = setInterval(async () => {
|
|
|
+ if (!this.hasInit || !this.option?.taskId) {
|
|
|
+ console.debug('[AgoraSTT:STT] Monitor stopping: no initialization or taskId')
|
|
|
+ clearInterval(monitorInterval)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const status = await this.queryTranscription()
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription monitor status:', status)
|
|
|
+
|
|
|
+ // 如果转录已停止,清除监控
|
|
|
+ if (status.status === 'STOPPED' || status.status === 'FAILED') {
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription stopped, clearing monitor')
|
|
|
+ clearInterval(monitorInterval)
|
|
|
+ } else if (status.status === 'STARTED') {
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription is running normally')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[AgoraSTT:STT] Transcription monitor error:', error)
|
|
|
+ // 如果查询失败,可能是任务已过期,停止监控
|
|
|
+ if (error instanceof Error && error.message && error.message.includes('not found')) {
|
|
|
+ console.debug('[AgoraSTT:STT] Task not found, stopping monitor')
|
|
|
+ clearInterval(monitorInterval)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, 5000) // 每5秒查询一次
|
|
|
+
|
|
|
+ // 10分钟后自动停止监控
|
|
|
+ setTimeout(() => {
|
|
|
+ clearInterval(monitorInterval)
|
|
|
+ console.debug('[AgoraSTT:STT] Transcription monitor timeout')
|
|
|
+ }, 10 * 60 * 1000)
|
|
|
+ }
|
|
|
}
|