package filetrans_test import ( "fmt" "testing" "time" "yunyan/sys/aliyun/filetrans" ) // 老 key:公共端点 dashscope.aliyuncs.com + paraformer-v2(8 语种) const testApiKey = "sk-ec05b3b04275433ea4f4ea8e5299a8cf" // 新 key:工作空间端点 + qwen-audio-3.0-asr-flash-filetrans(27 语种,含越南语) const ( testWorkspaceId = "ws-j6yhdqqhxb6hglee" testWorkspaceKey = "sk-ws-H.ERXDMMY.8sEM.MEUCIDeZPGn6VJdlGEoWwhLG-w_2c4OT2IZSmmucug1sFPtmAiEA79Se7JiZ7CXw5AB33r3zXvSHPqwtcL7fThJSrq1e-gM" ) const testVietnameseAudio = "https://oss.ymaikj.com/EAIMAR/User/1942916924698525696/LocalAudio/2026/02/27/jLEIQzYIAnqy.wav" // 注意 language 传的是 **短码**(language_hints 格式,即 toDashScopeLang 的输出),不是 BCP-47。 // 传 "vi-VN" 会被 CreateTask 的语种校验直接拒掉。 func TestCreateTask(t *testing.T) { sys, err := filetrans.NewSys( filetrans.SetApiKey(testApiKey), ) if err != nil { t.Fatalf("初始化失败: %v", err) } taskID, err := sys.CreateTask(testVietnameseAudio, "zh", true, "") if err != nil { t.Fatalf("创建任务失败: %v", err) } fmt.Printf("创建任务成功: taskID=%s\n", taskID) } // TestCreateTaskVietnamese 验证新模型的越南语转写。 // ⚠️ 前置条件:workspace ws-j6yhdqqhxb6hglee 下需已开通 qwen-audio-3.0-asr-flash-filetrans // 且该 API Key 有该模型的调用权限,否则返回 Model.AccessDenied。 func TestCreateTaskVietnamese(t *testing.T) { sys, err := filetrans.NewSys( filetrans.SetApiKey(testWorkspaceKey), filetrans.SetWorkspaceId(testWorkspaceId), ) if err != nil { t.Fatalf("初始化失败: %v", err) } taskID, err := sys.CreateTask(testVietnameseAudio, "vi", true, "") if err != nil { t.Fatalf("创建任务失败: %v", err) } fmt.Printf("越南语任务提交成功: taskID=%s\n", taskID) for i := 0; i < 60; i++ { time.Sleep(5 * time.Second) status, contexts, err := sys.QueryTask(taskID) fmt.Printf(" 轮询 #%d: status=%s\n", i+1, status) if err != nil { t.Fatalf("查询失败: %v", err) } if status == filetrans.StatusSuccess { if len(contexts) == 0 { t.Fatal("转写结果为空——这正是不支持语种时的典型表现,需复核模型语种支持") } for j, ctx := range contexts { fmt.Printf(" [%d] %dms-%dms Speaker(%s): %s\n", j, ctx.StartTime, ctx.EndTime, ctx.Speaker, ctx.Content) } return } if status == filetrans.StatusFailed { t.Fatal("任务失败") } } t.Fatal("超时:任务未在 5 分钟内完成") } // TestUnsupportedLangRejected 钉住 fail-fast 语义:不支持的语种必须当场报错, // 绝不能放行给阿里(阿里不报错,只会静默返回空转写)。 func TestUnsupportedLangRejected(t *testing.T) { sys, err := filetrans.NewSys(filetrans.SetApiKey(testApiKey)) // 无 workspace → paraformer-v2 if err != nil { t.Fatalf("初始化失败: %v", err) } if _, err := sys.CreateTask(testVietnameseAudio, "vi", true, ""); err == nil { t.Fatal("paraformer-v2 不支持越南语,CreateTask 必须报错") } if _, err := sys.CreateTask(testVietnameseAudio, "vi-VN", true, ""); err == nil { t.Fatal("language_hints 只认短码,BCP-47 格式必须报错") } } func TestQueryTask(t *testing.T) { sys, err := filetrans.NewSys( filetrans.SetApiKey(testApiKey), ) if err != nil { t.Fatalf("初始化失败: %v", err) } // 替换为 TestCreateTask 返回的实际 taskID taskID := "1c09487e-9e92-4c4d-ba62-a442bacfc309" status, contexts, err := sys.QueryTask(taskID) if err != nil { t.Fatalf("查询失败: %v", err) } fmt.Printf("查询结果: status=%s\n", status) for i, ctx := range contexts { fmt.Printf(" [%d] %dms-%dms Speaker(%s): %s\n", i, ctx.StartTime, ctx.EndTime, ctx.Speaker, ctx.Content) } } func TestCreateAndPollTask(t *testing.T) { sys, err := filetrans.NewSys( filetrans.SetApiKey(testApiKey), ) if err != nil { t.Fatalf("初始化失败: %v", err) } taskID, err := sys.CreateTask( "https://oss.ymaikj.com/EAIMAR/User/2014183956768882688/LocalAudio/2026/01/22/kUqCZgiVkspH.wav", "zh", true, "", ) if err != nil { t.Fatalf("创建任务失败: %v", err) } fmt.Printf("任务已提交: taskID=%s\n", taskID) for i := 0; i < 60; i++ { time.Sleep(5 * time.Second) status, contexts, err := sys.QueryTask(taskID) fmt.Printf(" 轮询 #%d: status=%s\n", i+1, status) if err != nil { t.Fatalf("查询失败: %v", err) } if status == filetrans.StatusSuccess { fmt.Printf("转写完成,共 %d 条结果:\n", len(contexts)) for j, ctx := range contexts { fmt.Printf(" [%d] %dms-%dms Speaker(%s): %s\n", j, ctx.StartTime, ctx.EndTime, ctx.Speaker, ctx.Content) } return } if status == filetrans.StatusFailed { t.Fatalf("任务失败") } } t.Fatal("超时:任务未在 5 分钟内完成") }