讯飞开放平台语音转写 golang实现demo
讯飞开放平台语音转写 golang实现demo:
package main
import (
"bytes"
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"time"
)
func main() {
appId := "your appId"
secretKey := "your secretKey"
filePath := "upload file path"
// 上传转写音频获取orderId
orderId, err := upload(appId, secretKey, filePath)
if err != nil {
log.Fatal(err)
}
// 根据orderId 获取结果
res, err := getOrderResult(appId, secretKey, orderId)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
type uploadRes struct {
Code string `json:"code"`
DescInfo string `json:"descInfo"`
Content struct {
OrderId string `json:"orderId"` // 订单id
TaskEstimateTime int `json:"taskEstimateTime"` // 订单预估耗时,单位毫秒
} `json:"content"`
}
type getOrderResultRes struct {
Code string `json:"code"`
DescInfo string `json:"descInfo"`
Content struct {
OrderInfo struct {
OrderId string `json:"orderId"` // 订单id
FailType int `json:"failType"` // 订单失败类型,处理成功时响应0
Status int `json:"status"` // 订单流程状态
OriginalDuration int `json:"originalDuration"` // 上传设置音频时长,单位毫秒
RealDuration int `json:"realDuration"` // 实际处理音频时长,单位毫秒
ExpireTime int `json:"expireTime"` // 已完成订单删除时间戳,毫秒
} `json:"orderInfo"`
OrderResult string `json:"orderResult"` // 转写结果,json字符串
} `json:"content"`
TaskEstimateTime int `json:"taskEstimateTime"` // 订单预估耗时,单位毫秒
}
// upload 上传音频文件 获取订单ID
func upload(appId, secretKey, filePath string) (string, error) {
// 获取文件名称
fileName := filepath.Base(filePath)
file, err := os.Open(filePath)
if err != nil {
return "", err
}
// 获取文件大小
stat, err := file.Stat()
if err != nil {
return "", err
}
fileSize := strconv.FormatInt(stat.Size(), 10)
// 读取文件
fileBytes, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
// 生成签名
ts := fmt.Sprintf("%d", time.Now().Unix())
signa := generateSignature(appId, secretKey, ts)
// 上传
client := &http.Client{}
// 拼装请求信息
request, _ := http.NewRequest("POST", "https://raasr.xfyun.cn/v2/api/upload", bytes.NewReader(fileBytes))
// 请求参数(此处为必填项,其余参数参考文档)
q := request.URL.Query()
q.Add("appId", appId)
q.Add("ts", ts)
q.Add("signa", signa)
q.Add("fileName", fileName)
q.Add("fileSize", fileSize)
q.Add("duration", "0")
request.URL.RawQuery = q.Encode()
// 设置请求头
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
request.Header.Set("Chunked", "false")
//处理返回结果
response, _ := client.Do(request)
defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
var res uploadRes
_ = json.Unmarshal(body, &res)
if res.Code == "000000" {
return res.Content.OrderId, nil
}
return "", errors.New("res error :" + res.DescInfo)
}
// getOrderResult 获取订单结果
func getOrderResult(appId, secretKey, orderId string) (string, error) {
// 生成签名
ts := fmt.Sprintf("%d", time.Now().Unix())
signa := generateSignature(appId, secretKey, ts)
// 获取结果
client := &http.Client{}
request, _ := http.NewRequest("GET", "https://raasr.xfyun.cn/v2/api/getResult", nil)
// 请求参数
q := request.URL.Query()
q.Add("appId", appId)
q.Add("ts", ts)
q.Add("signa", signa)
q.Add("orderId", orderId)
q.Add("resultType", "transfer")
request.URL.RawQuery = q.Encode()
// 设置请求头
request.Header.Set("Content-Type", "multipart/form-data")
//处理返回结果
response, _ := client.Do(request)
defer response.Body.Close()
body, _ := ioutil.ReadAll(response.Body)
var res getOrderResultRes
_ = json.Unmarshal(body, &res)
if res.Code == "000000" {
if res.Content.OrderInfo.Status != 4 {
return "", errors.New(fmt.Sprintf("transfer err: status %d,failType %d", res.Content.OrderInfo.Status, res.Content.OrderInfo.FailType))
}
// 处理转写结果
return orderResultHandle(res.Content.OrderResult)
}
return "", errors.New("res error :" + res.DescInfo)
}
// generateSignature 生成签名
func generateSignature(appId, secretKey, ts string) string {
// 拼接字符串
baseString := appId + ts
// md5
hasher := md5.New()
hasher.Write([]byte(baseString))
hashInBytes := hasher.Sum(nil)
md5BaseString := hex.EncodeToString(hashInBytes)
// HmacSHA1 加密
sha1Byte := hmacSHA1(secretKey, md5BaseString)
// base64
base64Str := base64.StdEncoding.EncodeToString(sha1Byte)
return base64Str
}
func hmacSHA1(key, message string) []byte {
keyBytes := []byte(key)
messageBytes := []byte(message)
mac := hmac.New(sha1.New, keyBytes)
mac.Write(messageBytes)
return mac.Sum(nil)
}
type orderResult struct {
Lattice []struct {
Json1best string `json:"json_1best"`
} `json:"lattice"` // 顺滑处理后的结果 是字符串
Lattice2 []lattice `json:"lattice2"` // 未顺滑处理的结果 是json对象
}
// Lattice 单句转写结果
type lattice struct {
Lid string `json:"lid"`
Begin string `json:"begin"`
End string `json:"end"`
Json1best json1best `json:"json_1best"`
}
// json1best 单句转写结果
type json1best struct {
St st `json:"st"`
}
// st 单句转写结果
type st struct {
Sc string `json:"sc"`
Pa string `json:"pa"`
Rt []rt `json:"rt"`
}
// rt 词语识别结果
type rt struct {
Nb string `json:"nb"`
Nc string `json:"nc"`
Ws []ws `json:"ws"`
}
// ws 词语识别结果
type ws struct {
Wb int64 `json:"wb"` // 词语开始的帧数(注一帧 10ms),位置是相对 bg,仅支持中、英文语种
We int64 `json:"we"` // 词语结束的帧数(注一帧 10ms),位置是相对 bg,仅支持中、英文语种
Cw []cw `json:"cw"` // 词语候选识别结果集合
}
// Cw 词语识别结果
type cw struct {
W string `json:"w"` // 识别结果
Wp string `json:"wp"` // 词语的属性 n:正常词 s:顺滑 p:标点 g:分段(按此标识进行分段)
Wc string `json:"wc"`
}
func orderResultHandle(orderResultStr string) (string, error) {
var res orderResult
err := json.Unmarshal([]byte(orderResultStr), &res)
if err != nil {
return "", err
}
var spliceStr string
for _, la := range res.Lattice2 {
for _, rt := range la.Json1best.St.Rt {
for _, ws := range rt.Ws {
if len(ws.Cw) > 0 {
cw := ws.Cw[0]
if cw.Wp == "g" {
spliceStr += "\n"
} else {
spliceStr += cw.W
}
}
}
}
}
return spliceStr, nil
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!