|
|
@@ -0,0 +1,428 @@
|
|
|
+import { useState, useEffect } from "react"
|
|
|
+import { Card, Button, Input, Form, message, Space, Typography, Divider, Alert } from "antd"
|
|
|
+import {
|
|
|
+ InfoCircleOutlined,
|
|
|
+ PlayCircleOutlined,
|
|
|
+ StopOutlined,
|
|
|
+ ReloadOutlined,
|
|
|
+} from "@ant-design/icons"
|
|
|
+import { useNavigate } from "react-router-dom"
|
|
|
+import { genRandomUserId } from "@/common"
|
|
|
+
|
|
|
+import styles from "./index.module.scss"
|
|
|
+
|
|
|
+// 导入SDK核心模块
|
|
|
+import { SttSdk } from "../../../packages/stt-sdk-core/src"
|
|
|
+import type { ISttManagerAdapter, IRtmManagerAdapter } from "../../../packages/stt-sdk-core/src"
|
|
|
+
|
|
|
+const { Title, Text } = Typography
|
|
|
+
|
|
|
+const SdkTestPage = () => {
|
|
|
+ const nav = useNavigate()
|
|
|
+ const [messageApi, contextHolder] = message.useMessage()
|
|
|
+
|
|
|
+ const [form] = Form.useForm()
|
|
|
+ const [sdk, setSdk] = useState<SttSdk | null>(null)
|
|
|
+ const [sttManager, setSttManager] = useState<ISttManagerAdapter | null>(null)
|
|
|
+ const [rtmManager, setRtmManager] = useState<IRtmManagerAdapter | null>(null)
|
|
|
+ const [isSdkInitialized, setIsSdkInitialized] = useState(false)
|
|
|
+ const [isSttManagerInitialized, setIsSttManagerInitialized] = useState(false)
|
|
|
+ const [isRtmManagerJoined, setIsRtmManagerJoined] = useState(false)
|
|
|
+ const [isTranscriptionActive, setIsTranscriptionActive] = useState(false)
|
|
|
+ const [transcriptionStatus, setTranscriptionStatus] = useState<string>("idle")
|
|
|
+ const [testResults, setTestResults] = useState<string[]>([])
|
|
|
+
|
|
|
+ // 添加测试日志
|
|
|
+ const addTestLog = (log: string) => {
|
|
|
+ setTestResults((prev) => [...prev, `${new Date().toLocaleTimeString()}: ${log}`])
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化SDK
|
|
|
+ const initializeSdk = async (values: {
|
|
|
+ appId: string
|
|
|
+ certificate: string
|
|
|
+ channel: string
|
|
|
+ userName: string
|
|
|
+ }) => {
|
|
|
+ try {
|
|
|
+ addTestLog("开始初始化SDK...")
|
|
|
+
|
|
|
+ const newSdk = new SttSdk()
|
|
|
+ await newSdk.initialize({
|
|
|
+ appId: values.appId,
|
|
|
+ certificate: values.certificate,
|
|
|
+ logLevel: "info",
|
|
|
+ })
|
|
|
+
|
|
|
+ setSdk(newSdk)
|
|
|
+ setIsSdkInitialized(true)
|
|
|
+ addTestLog("✅ SDK初始化成功")
|
|
|
+
|
|
|
+ // 创建管理器
|
|
|
+ const sttManager = newSdk.createSttManager()
|
|
|
+ const rtmManager = newSdk.createRtmManager()
|
|
|
+
|
|
|
+ setSttManager(sttManager)
|
|
|
+ setRtmManager(rtmManager)
|
|
|
+ addTestLog("✅ STT和RTM管理器创建成功")
|
|
|
+
|
|
|
+ messageApi.success("SDK初始化成功")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ SDK初始化失败: ${error}`)
|
|
|
+ messageApi.error(`SDK初始化失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化STT管理器
|
|
|
+ const initializeSttManager = async () => {
|
|
|
+ if (!sttManager || !form) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ const values = form.getFieldsValue()
|
|
|
+ addTestLog("开始初始化STT管理器...")
|
|
|
+
|
|
|
+ await sttManager.init({
|
|
|
+ userId: genRandomUserId(),
|
|
|
+ channel: values.channel,
|
|
|
+ userName: values.userName,
|
|
|
+ })
|
|
|
+
|
|
|
+ setIsSttManagerInitialized(true)
|
|
|
+ addTestLog("✅ STT管理器初始化成功")
|
|
|
+ messageApi.success("STT管理器初始化成功")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ STT管理器初始化失败: ${error}`)
|
|
|
+ messageApi.error(`STT管理器初始化失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加入RTM频道
|
|
|
+ const joinRtmChannel = async () => {
|
|
|
+ if (!rtmManager || !form) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ const values = form.getFieldsValue()
|
|
|
+ addTestLog("开始加入RTM频道...")
|
|
|
+
|
|
|
+ await rtmManager.join({
|
|
|
+ channel: values.channel,
|
|
|
+ userId: genRandomUserId().toString(),
|
|
|
+ userName: values.userName,
|
|
|
+ })
|
|
|
+
|
|
|
+ setIsRtmManagerJoined(true)
|
|
|
+ addTestLog("✅ RTM频道加入成功")
|
|
|
+ messageApi.success("RTM频道加入成功")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ RTM频道加入失败: ${error}`)
|
|
|
+ messageApi.error(`RTM频道加入失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 开始转录
|
|
|
+ const startTranscription = async () => {
|
|
|
+ if (!sttManager) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ addTestLog("开始语音转录...")
|
|
|
+ setTranscriptionStatus("starting")
|
|
|
+
|
|
|
+ await sttManager.startTranscription({
|
|
|
+ languages: [{ source: "en-US", target: ["zh-CN"] }],
|
|
|
+ })
|
|
|
+
|
|
|
+ setIsTranscriptionActive(true)
|
|
|
+ setTranscriptionStatus("active")
|
|
|
+ addTestLog("✅ 语音转录已开始")
|
|
|
+ messageApi.success("语音转录已开始")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ 语音转录启动失败: ${error}`)
|
|
|
+ setTranscriptionStatus("error")
|
|
|
+ messageApi.error(`语音转录启动失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 停止转录
|
|
|
+ const stopTranscription = async () => {
|
|
|
+ if (!sttManager) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ addTestLog("停止语音转录...")
|
|
|
+ setTranscriptionStatus("stopping")
|
|
|
+
|
|
|
+ await sttManager.stopTranscription()
|
|
|
+
|
|
|
+ setIsTranscriptionActive(false)
|
|
|
+ setTranscriptionStatus("stopped")
|
|
|
+ addTestLog("✅ 语音转录已停止")
|
|
|
+ messageApi.success("语音转录已停止")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ 语音转录停止失败: ${error}`)
|
|
|
+ setTranscriptionStatus("error")
|
|
|
+ messageApi.error(`语音转录停止失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询转录状态
|
|
|
+ const queryTranscription = async () => {
|
|
|
+ if (!sttManager) return
|
|
|
+
|
|
|
+ try {
|
|
|
+ addTestLog("查询转录状态...")
|
|
|
+
|
|
|
+ const result = await sttManager.queryTranscription()
|
|
|
+ addTestLog(`📊 转录状态查询结果: ${JSON.stringify(result)}`)
|
|
|
+ messageApi.info("转录状态查询完成,查看日志了解详情")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ 转录状态查询失败: ${error}`)
|
|
|
+ messageApi.error(`转录状态查询失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理资源
|
|
|
+ const cleanup = async () => {
|
|
|
+ try {
|
|
|
+ addTestLog("开始清理资源...")
|
|
|
+
|
|
|
+ if (isTranscriptionActive && sttManager) {
|
|
|
+ await stopTranscription()
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sttManager) {
|
|
|
+ await sttManager.destroy()
|
|
|
+ setSttManager(null)
|
|
|
+ setIsSttManagerInitialized(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rtmManager) {
|
|
|
+ await rtmManager.destroy()
|
|
|
+ setRtmManager(null)
|
|
|
+ setIsRtmManagerJoined(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sdk) {
|
|
|
+ await sdk.destroy()
|
|
|
+ setSdk(null)
|
|
|
+ setIsSdkInitialized(false)
|
|
|
+ }
|
|
|
+
|
|
|
+ addTestLog("✅ 资源清理完成")
|
|
|
+ setTranscriptionStatus("idle")
|
|
|
+ messageApi.success("资源清理完成")
|
|
|
+ } catch (error) {
|
|
|
+ addTestLog(`❌ 资源清理失败: ${error}`)
|
|
|
+ messageApi.error(`资源清理失败: ${error}`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回主应用
|
|
|
+ const goToMainApp = () => {
|
|
|
+ nav("/home")
|
|
|
+ }
|
|
|
+
|
|
|
+ // 组件卸载时清理资源
|
|
|
+ useEffect(() => {
|
|
|
+ return () => {
|
|
|
+ if (sdk) {
|
|
|
+ cleanup()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [sdk])
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={styles.sdkTestPage}>
|
|
|
+ {contextHolder}
|
|
|
+
|
|
|
+ <div className={styles.header}>
|
|
|
+ <Title level={2}>🎯 SDK 功能测试页面</Title>
|
|
|
+ <Text type="secondary">测试 STT SDK 核心功能的集成和兼容性</Text>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className={styles.content}>
|
|
|
+ <div className={styles.leftPanel}>
|
|
|
+ <Card title="🔧 SDK 配置" className={styles.configCard}>
|
|
|
+ <Form
|
|
|
+ form={form}
|
|
|
+ layout="vertical"
|
|
|
+ initialValues={{
|
|
|
+ appId: import.meta.env.VITE_AGORA_APP_ID || "",
|
|
|
+ certificate: "",
|
|
|
+ channel: `test-channel-${Date.now()}`,
|
|
|
+ userName: `TestUser-${Date.now()}`,
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Form.Item
|
|
|
+ label="App ID"
|
|
|
+ name="appId"
|
|
|
+ rules={[{ required: true, message: "请输入 App ID" }]}
|
|
|
+ >
|
|
|
+ <Input placeholder="请输入 Agora App ID" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="Certificate"
|
|
|
+ name="certificate"
|
|
|
+ rules={[{ required: true, message: "请输入 Certificate" }]}
|
|
|
+ >
|
|
|
+ <Input.Password placeholder="请输入 Agora Certificate" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="频道名称"
|
|
|
+ name="channel"
|
|
|
+ rules={[{ required: true, message: "请输入频道名称" }]}
|
|
|
+ >
|
|
|
+ <Input placeholder="请输入频道名称" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item
|
|
|
+ label="用户名称"
|
|
|
+ name="userName"
|
|
|
+ rules={[{ required: true, message: "请输入用户名称" }]}
|
|
|
+ >
|
|
|
+ <Input placeholder="请输入用户名称" />
|
|
|
+ </Form.Item>
|
|
|
+
|
|
|
+ <Form.Item>
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={() => initializeSdk(form.getFieldsValue())}
|
|
|
+ disabled={isSdkInitialized}
|
|
|
+ >
|
|
|
+ {isSdkInitialized ? "✅ 已初始化" : "初始化 SDK"}
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button onClick={cleanup} danger disabled={!isSdkInitialized}>
|
|
|
+ 清理资源
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ <Card title="🚀 功能测试" className={styles.testCard}>
|
|
|
+ <Space direction="vertical" style={{ width: "100%" }}>
|
|
|
+ <Button
|
|
|
+ onClick={initializeSttManager}
|
|
|
+ disabled={!isSdkInitialized || isSttManagerInitialized}
|
|
|
+ block
|
|
|
+ >
|
|
|
+ {isSttManagerInitialized ? "✅ STT管理器已初始化" : "初始化STT管理器"}
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ onClick={joinRtmChannel}
|
|
|
+ disabled={!isSdkInitialized || isRtmManagerJoined}
|
|
|
+ block
|
|
|
+ >
|
|
|
+ {isRtmManagerJoined ? "✅ RTM频道已加入" : "加入RTM频道"}
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Divider />
|
|
|
+
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<PlayCircleOutlined />}
|
|
|
+ onClick={startTranscription}
|
|
|
+ disabled={!isSttManagerInitialized || isTranscriptionActive}
|
|
|
+ block
|
|
|
+ >
|
|
|
+ {isTranscriptionActive ? "转录进行中..." : "开始转录"}
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ danger
|
|
|
+ icon={<StopOutlined />}
|
|
|
+ onClick={stopTranscription}
|
|
|
+ disabled={!isTranscriptionActive}
|
|
|
+ block
|
|
|
+ >
|
|
|
+ 停止转录
|
|
|
+ </Button>
|
|
|
+
|
|
|
+ <Button
|
|
|
+ icon={<ReloadOutlined />}
|
|
|
+ onClick={queryTranscription}
|
|
|
+ disabled={!isTranscriptionActive}
|
|
|
+ block
|
|
|
+ >
|
|
|
+ 查询状态
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+
|
|
|
+ <Divider />
|
|
|
+
|
|
|
+ <Alert
|
|
|
+ message="转录状态"
|
|
|
+ description={
|
|
|
+ transcriptionStatus === "idle"
|
|
|
+ ? "等待开始转录"
|
|
|
+ : transcriptionStatus === "starting"
|
|
|
+ ? "正在启动转录..."
|
|
|
+ : transcriptionStatus === "active"
|
|
|
+ ? "转录进行中"
|
|
|
+ : transcriptionStatus === "stopping"
|
|
|
+ ? "正在停止转录..."
|
|
|
+ : transcriptionStatus === "stopped"
|
|
|
+ ? "转录已停止"
|
|
|
+ : "状态异常"
|
|
|
+ }
|
|
|
+ type={
|
|
|
+ transcriptionStatus === "active"
|
|
|
+ ? "success"
|
|
|
+ : transcriptionStatus === "error"
|
|
|
+ ? "error"
|
|
|
+ : "info"
|
|
|
+ }
|
|
|
+ showIcon
|
|
|
+ />
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className={styles.rightPanel}>
|
|
|
+ <Card title="📋 测试日志" className={styles.logCard}>
|
|
|
+ <div className={styles.logContainer}>
|
|
|
+ {testResults.length === 0 ? (
|
|
|
+ <Text type="secondary">暂无测试日志,请开始测试...</Text>
|
|
|
+ ) : (
|
|
|
+ testResults.map((log, index) => (
|
|
|
+ <div key={index} className={styles.logEntry}>
|
|
|
+ {log}
|
|
|
+ </div>
|
|
|
+ ))
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {testResults.length > 0 && (
|
|
|
+ <Button onClick={() => setTestResults([])} size="small" style={{ marginTop: 16 }}>
|
|
|
+ 清空日志
|
|
|
+ </Button>
|
|
|
+ )}
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ <Card title="💡 使用说明" className={styles.infoCard}>
|
|
|
+ <Space direction="vertical" style={{ width: "100%" }}>
|
|
|
+ <Text type="secondary">
|
|
|
+ <InfoCircleOutlined /> 测试步骤:
|
|
|
+ </Text>
|
|
|
+ <ol>
|
|
|
+ <li>填写 App ID 和 Certificate</li>
|
|
|
+ <li>点击"初始化 SDK"</li>
|
|
|
+ <li>初始化 STT 管理器和加入 RTM 频道</li>
|
|
|
+ <li>开始/停止转录测试</li>
|
|
|
+ <li>查看测试日志了解详细结果</li>
|
|
|
+ </ol>
|
|
|
+
|
|
|
+ <Button type="link" onClick={goToMainApp}>
|
|
|
+ 返回主应用
|
|
|
+ </Button>
|
|
|
+ </Space>
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+export default SdkTestPage
|