115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
// 使用公共类型定义
|
|
import type {
|
|
AudioItem,
|
|
TranscriptionResult,
|
|
TranscriptionResponse,
|
|
TranscriptionData
|
|
} from '@gold/config/types'
|
|
|
|
/**
|
|
* API 服务接口(需要从应用层注入)
|
|
*/
|
|
interface ApiService {
|
|
videoToCharacters: (data: { fileLinkList: string[] }) => Promise<{ data: string }>
|
|
}
|
|
|
|
// 全局 API 服务实例(由应用层设置)
|
|
let apiServiceInstance: ApiService | null = null
|
|
|
|
/**
|
|
* 设置 API 服务实例
|
|
* @param service - API 服务对象
|
|
*/
|
|
export function setApiService(service: ApiService) {
|
|
apiServiceInstance = service
|
|
}
|
|
|
|
/**
|
|
* 将音频列表转换为文本转录
|
|
* @param list - 音频项列表
|
|
* @param apiService - API 服务实例(可选,如果已通过 setApiService 设置则不需要)
|
|
* @returns 转录结果数组
|
|
* @throws 当转录过程出错时抛出错误
|
|
*
|
|
* @example
|
|
* const audioList = [{ audio_url: 'https://example.com/audio.mp3' }]
|
|
* const transcriptions = await getVoiceText(audioList)
|
|
* console.log(transcriptions) // [{ key: 'url', value: 'transcribed text' }]
|
|
*/
|
|
export async function getVoiceText(
|
|
list: AudioItem[],
|
|
apiService?: ApiService
|
|
): Promise<TranscriptionResult[]> {
|
|
// 使用传入的 apiService 或全局实例
|
|
const service = apiService || apiServiceInstance
|
|
|
|
if (!service) {
|
|
throw new Error('getVoiceText: 需要提供 API 服务实例。请使用 setApiService() 设置或传入 apiService 参数')
|
|
}
|
|
|
|
// 调用API将视频转换为文本
|
|
const ret = await service.videoToCharacters({
|
|
fileLinkList: list.map(item => item.audio_url),
|
|
})
|
|
|
|
// 解析响应数据
|
|
const data: string = ret.data
|
|
const rst: TranscriptionResponse = JSON.parse(data)
|
|
const transcription_url: string[] = rst.results.map(item => item.transcription_url)
|
|
|
|
// 并行获取所有转录内容
|
|
const transcriptions: TranscriptionResult[] = await Promise.all(
|
|
(transcription_url || []).filter(Boolean).map(async (url: string): Promise<TranscriptionResult> => {
|
|
try {
|
|
const resp: Response = await fetch(url)
|
|
const contentType: string = resp.headers.get('content-type') || ''
|
|
const value: string = contentType.includes('application/json')
|
|
? JSON.stringify(await resp.json())
|
|
: await resp.text()
|
|
const parsed: TranscriptionData = JSON.parse(value)
|
|
return {
|
|
key: url,
|
|
audio_url: parsed.file_url,
|
|
value: parsed.transcripts?.[0]?.text || ''
|
|
}
|
|
} catch (e: unknown) {
|
|
console.warn('获取转写内容失败:', url, e)
|
|
return { key: url, value: '' }
|
|
}
|
|
})
|
|
)
|
|
return transcriptions
|
|
}
|
|
|
|
/**
|
|
* Hook 返回值接口
|
|
*/
|
|
interface UseVoiceTextReturn {
|
|
getVoiceText: (list: AudioItem[], apiService?: ApiService) => Promise<TranscriptionResult[]>
|
|
}
|
|
|
|
/**
|
|
* 语音文本转换 Hook
|
|
* @param apiService - API 服务实例(可选,如果已通过 setApiService 设置则不需要)
|
|
* @returns 包含 getVoiceText 方法的对象
|
|
*
|
|
* @example
|
|
* // 方式一:使用全局设置的 API 服务
|
|
* setApiService(myApiService)
|
|
* const { getVoiceText } = useVoiceText()
|
|
* const result = await getVoiceText(audioList)
|
|
*
|
|
* @example
|
|
* // 方式二:传入 API 服务实例
|
|
* const { getVoiceText } = useVoiceText()
|
|
* const result = await getVoiceText(audioList, myApiService)
|
|
*/
|
|
export default function useVoiceText(apiService?: ApiService): UseVoiceTextReturn {
|
|
return {
|
|
getVoiceText: (list: AudioItem[]) => getVoiceText(list, apiService)
|
|
}
|
|
}
|
|
|
|
|
|
|