From 519ec7e0a751e0784340e6c72b42222ebe0de12f Mon Sep 17 00:00:00 2001 From: 641453620 <641453620@qq.com> Date: Sun, 26 Apr 2020 12:18:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E=EF=BC=9A?= =?UTF-8?q?=201.=E4=BF=AE=E5=A4=8D=E9=98=BF=E9=87=8C=E4=BA=91=E6=B5=B7?= =?UTF-8?q?=E5=A4=96=E5=9C=B0=E5=8C=BA=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=97=AE=E9=A2=98=202.=E6=94=AF=E6=8C=81=E6=97=A5=E8=AF=AD=203?= =?UTF-8?q?.=E6=94=AF=E6=8C=81=E8=BE=93=E5=87=BA=E5=8F=8C=E8=AF=AD?= =?UTF-8?q?=E7=9A=84TXT=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/aliyun/engine.go | 84 ++++++++++++++++++++++++++++++++++++-------- app/data.go | 16 ++++++++- app/event.go | 13 +++++++ app/srt.go | 65 +++++++++++++++++++++++----------- app/video.go | 67 ++++++++++++++++++++++++----------- main.go | 8 ++--- 6 files changed, 192 insertions(+), 61 deletions(-) diff --git a/app/aliyun/engine.go b/app/aliyun/engine.go index c79c5c7..a626672 100644 --- a/app/aliyun/engine.go +++ b/app/aliyun/engine.go @@ -3,17 +3,24 @@ package aliyun import ( "encoding/json" "errors" + "fmt" "github.com/aliyun/alibaba-cloud-sdk-go/sdk" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "strconv" "time" ) +const ( + ALIYUN_CLOUND_REGION_CHA = 1 //中国 + ALIYUN_CLOUND_REGION_INT = 2 //海外 +) + //阿里云语音识别引擎 type AliyunClound struct { AccessKeyId string AccessKeySecret string AppKey string + Region int } @@ -38,12 +45,20 @@ type AliyunAudioWord struct { } -// 地域ID,常量内容,请勿改变 -const REGION_ID string = "cn-shanghai" -const ENDPOINT_NAME string = "cn-shanghai" -const PRODUCT string = "nls-filetrans" -const DOMAIN string = "filetrans.cn-shanghai.aliyuncs.com" -const API_VERSION string = "2018-08-17" +// 定义常量 +const REGION_ID_REGION_INT string = "ap-southeast-1" +const ENDPOINT_NAME_REGION_INT string = "ap-southeast-1" +const PRODUCT_REGION_INT string = "nls-filetrans" +const DOMAIN_REGION_INT string = "filetrans.ap-southeast-1.aliyuncs.com" +const API_VERSION_REGION_INT string = "2019-08-23" + +const REGION_ID_REGION_CHA string = "cn-shanghai" +const ENDPOINT_NAME_REGION_CHA string = "cn-shanghai" +const PRODUCT_REGION_CHA string = "nls-filetrans" +const DOMAIN_REGION_CHA string = "filetrans.cn-shanghai.aliyuncs.com" +const API_VERSION_REGION_CHA string = "2018-08-17" + + const POST_REQUEST_ACTION string = "SubmitTask" const GET_REQUEST_ACTION string = "GetTaskResult" // 请求参数key @@ -51,6 +66,14 @@ const KEY_APP_KEY string = "appkey" const KEY_FILE_LINK string = "file_link" const KEY_VERSION string = "version" const KEY_ENABLE_WORDS string = "enable_words" +//是否启用统一后处理,默认值为 false +const ENABLE_UNIFY_POST string = "enable_unify_post" +//是否打开ITN,中文数字将转为阿拉伯数字输出,默认值为 false +//开启时需要设置version为”4.0”, enable_unify_post 必须为 true +const ENABLE_INVERSE_TEXT_NORMALIZATION string = "enable_inverse_text_normalization" +//如需启用后处理模型,默认值为 chinese,开启时需要设置version为”4.0”, +//enable_unify_post 必须为 true,可选值为 english +const UNIFY_POST_MODEL_NAME string = "unify_post_model_name" // 响应参数key const KEY_TASK string = "Task" const KEY_TASK_ID string = "TaskId" @@ -65,19 +88,24 @@ const STATUS_QUEUEING string = "QUEUEING" //发起录音文件识别 //接口文档 https://help.aliyun.com/document_detail/90727.html?spm=a2c4g.11186623.6.581.691af6ebYsUkd1 func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , error) { - client, err := sdk.NewClientWithAccessKey(REGION_ID, c.AccessKeyId, c.AccessKeySecret) + regionId, domain, apiVersion, product := c.GetApiVariable() + + fmt.Println( regionId, domain, apiVersion, product , c.Region ) + + client, err := sdk.NewClientWithAccessKey(regionId, c.AccessKeyId, c.AccessKeySecret) if err != nil { return "" , client , err } client.SetConnectTimeout(time.Second * 20) postRequest := requests.NewCommonRequest() - postRequest.Domain = DOMAIN - postRequest.Version = API_VERSION - postRequest.Product = PRODUCT + postRequest.Domain = domain + postRequest.Version = apiVersion + postRequest.Product = product postRequest.ApiName = POST_REQUEST_ACTION postRequest.Method = "POST" + mapTask := make(map[string]string) mapTask[KEY_APP_KEY] = c.AppKey mapTask[KEY_FILE_LINK] = fileLink @@ -85,6 +113,12 @@ func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , erro mapTask[KEY_VERSION] = "4.0" // 设置是否输出词信息,默认为false,开启时需要设置version为4.0 mapTask[KEY_ENABLE_WORDS] = "true" + + //启用统一后处理 + //mapTask[ENABLE_UNIFY_POST] = "true" + //mapTask[ENABLE_INVERSE_TEXT_NORMALIZATION] = "true" + //mapTask[UNIFY_POST_MODEL_NAME] = "chinese" + // to json task, err := json.Marshal(mapTask) if err != nil { @@ -125,10 +159,12 @@ func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , erro //获取录音文件识别结果 //接口文档 https://help.aliyun.com/document_detail/90727.html?spm=a2c4g.11186623.6.581.691af6ebYsUkd1 func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , callback func(result []byte)) error { + _, domain, apiVersion, product := c.GetApiVariable() + getRequest := requests.NewCommonRequest() - getRequest.Domain = DOMAIN - getRequest.Version = API_VERSION - getRequest.Product = PRODUCT + getRequest.Domain = domain + getRequest.Version = apiVersion + getRequest.Product = product getRequest.ApiName = GET_REQUEST_ACTION getRequest.Method = "GET" getRequest.QueryParams[KEY_TASK_ID] = taskId @@ -172,11 +208,29 @@ func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , ca } + +//获取API常量 +func (c AliyunClound) GetApiVariable () (regionId string , domain string , apiVersion string , product string) { + if c.Region == 0 || c.Region == ALIYUN_CLOUND_REGION_CHA { + regionId = REGION_ID_REGION_CHA + domain = DOMAIN_REGION_CHA + apiVersion = API_VERSION_REGION_CHA + product = PRODUCT_REGION_CHA + } else if c.Region == ALIYUN_CLOUND_REGION_INT { + regionId = REGION_ID_REGION_INT + domain = DOMAIN_REGION_INT + apiVersion = API_VERSION_REGION_INT + product = PRODUCT_REGION_INT + } + return +} + //获取错误信息 func (c AliyunClound) GetErrorStatusTextMessage (statusText string) string { var code map[string]string = map[string]string{ - "USER_BIZDURATION_QUOTA_EXCEED":"单日免费额度超出限制", - "FILE_DOWNLOAD_FAILED":"文件访问失败,请检查OSS存储空间访问权限", + "REQUEST_APPKEY_UNREGISTERED":"阿里云智能语音项目未创建/无访问权限。请检查语音引擎Appkey是否填写错误;如果是海外地区,在软件创建语音引擎时,服务区域需要选择“海外”", + "USER_BIZDURATION_QUOTA_EXCEED":"单日2小时识别免费额度超出限制", + "FILE_DOWNLOAD_FAILED":"文件访问失败,请检查OSS存储空间访问权限。请将OSS存储空间设置为“公共读”", "FILE_TOO_LARGE":"音频文件超出512MB", "FILE_PARSE_FAILED":"音频文件解析失败,请检查音频文件是否有损坏", "UNSUPPORTED_SAMPLE_RATE":"采样率不匹配", diff --git a/app/data.go b/app/data.go index 40a3134..e00cceb 100644 --- a/app/data.go +++ b/app/data.go @@ -303,12 +303,26 @@ type AliyunEngineListCache struct { Engine [] *AliyunEngineCache } -//引擎选项 +//语音引擎选项 type EngineSelects struct { Id int Name string } +//阿里云语音引擎区域选项 +type AliyunEngineRegionSelects struct { + Id int + Name string +} + +//获取 阿里云语音引擎区域选项列表 +func GetAliyunEngineRegionOptionSelects() []*BaiduAuthTypeSelects { + return []*BaiduAuthTypeSelects{ + &BaiduAuthTypeSelects{Id:aliyun.ALIYUN_CLOUND_REGION_CHA , Name:"中国"}, + &BaiduAuthTypeSelects{Id:aliyun.ALIYUN_CLOUND_REGION_INT , Name:"海外"}, + } +} + //获取 引擎选项列表 func (speechEng *SpeechEngineAppStruct) GetEngineOptionsSelects() []*EngineSelects { engines := make([]*EngineSelects , 0) diff --git a/app/event.go b/app/event.go index 132e2f3..e96510f 100644 --- a/app/event.go +++ b/app/event.go @@ -9,6 +9,7 @@ import ( "path" "path/filepath" "strings" + "videosrt/app/aliyun" "videosrt/app/tool" "videosrt/app/translate" ) @@ -146,6 +147,8 @@ func(mw *MyMainWindow) RunSpeechEngineSetingDialog(owner walk.Form , confirmCall engine = new(AliyunEngineCache) + engine.Region = aliyun.ALIYUN_CLOUND_REGION_CHA //默认值 + Dialog{ AssignTo: &dlg, Title: "新建语音引擎", @@ -191,6 +194,16 @@ func(mw *MyMainWindow) RunSpeechEngineSetingDialog(owner walk.Form , confirmCall Text: Bind("AccessKeySecret"), }, + Label{ + Text: "服务区域:", + }, + ComboBox{ + Value: Bind("Region", SelRequired{}), + BindingMember: "Id", + DisplayMember: "Name", + Model: GetAliyunEngineRegionOptionSelects(), + }, + Label{ ColumnSpan: 2, Text: "说明:\r\n“语音识别” 目前使用的是阿里云语音服务商,请填写相关的引擎配置。", diff --git a/app/srt.go b/app/srt.go index 004a692..c17db84 100644 --- a/app/srt.go +++ b/app/srt.go @@ -1,6 +1,7 @@ package app import ( + "bytes" "errors" "fmt" "os" @@ -270,41 +271,65 @@ func (app *SrtTranslateApp) SrtOutputFile(file string , srtRows []*SrtRows , out _,_ = fd.WriteString("[ar:]\r\n[ti:]\r\n[al:]\r\n[by:]\r\n") } + //主字幕 bilingualAsc := app.TranslateCfg.OutputMainSubtitleInputLanguage - index := 0 + + //普通文本容器 + var txtOutputContent bytes.Buffer + var txtTransalteOutputContent bytes.Buffer + for _ , data := range srtRows { var linestr string - //拼接文本 - if outputType == OUTPUT_SRT { - if app.TranslateCfg.TranslateSwitch { - if app.TranslateCfg.BilingualSubtitleSwitch { - linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text , data.TranslateText , true , bilingualAsc) + //字幕、歌词文件处理 + if outputType == OUTPUT_SRT || outputType == OUTPUT_LRC { + //拼接 + if outputType == OUTPUT_SRT { + if app.TranslateCfg.TranslateSwitch { + if app.TranslateCfg.BilingualSubtitleSwitch { + linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text , data.TranslateText , true , bilingualAsc) + } else { + linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.TranslateText , "" , false , true) + } } else { - linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.TranslateText , "" , false , true) + linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text , "" , false , true) + } + } else if outputType == OUTPUT_LRC { + if app.TranslateCfg.TranslateSwitch { + linestr = MakeMusicLrcText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.TranslateText) + } else { + linestr = MakeMusicLrcText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text) } - } else { - linestr = MakeSubtitleText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text , "" , false , true) } - } else if outputType == OUTPUT_STRING { - if app.TranslateCfg.TranslateSwitch { - linestr = MakeText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.TranslateText) - } else { - linestr = MakeText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text) + + //写入行 + if _, e = fd.WriteString(linestr);e != nil { + panic("写入文件失败:" + e.Error()) } - } else if outputType == OUTPUT_LRC { + } else if outputType == OUTPUT_STRING { + //普通文本处理 + txtOutputContent.WriteString(data.Text) + txtOutputContent.WriteString("\r\n") + if app.TranslateCfg.TranslateSwitch { - linestr = MakeMusicLrcText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.TranslateText) - } else { - linestr = MakeMusicLrcText(index , data.TimeStartMilliSecond , data.TimeEndMilliSecond , data.Text) + txtTransalteOutputContent.WriteString(data.TranslateText) + txtTransalteOutputContent.WriteString("\r\n") } } - if _, e = fd.WriteString(linestr);e != nil { + index++ + } + + //写入文本文件 + if outputType == OUTPUT_STRING { + txtOutputContent.WriteString("\r\n\r\n\r\n\r\n\r\n") + if _, e = fd.WriteString(txtOutputContent.String());e != nil { + panic("写入文件失败:" + e.Error()) + } + if _, e = fd.WriteString(txtTransalteOutputContent.String());e != nil { panic("写入文件失败:" + e.Error()) } - index++ } } diff --git a/app/video.go b/app/video.go index 3216a86..e55bc4a 100644 --- a/app/video.go +++ b/app/video.go @@ -1,6 +1,7 @@ package app import ( + "bytes" "errors" "github.com/buger/jsonparser" "os" @@ -88,6 +89,7 @@ func (app *VideoSrt) InitAppConfig(oss *AliyunOssCache , engine *AliyunEngineCac app.AliyunClound.AppKey = engine.AppKey app.AliyunClound.AccessKeyId = engine.AccessKeyId app.AliyunClound.AccessKeySecret = engine.AccessKeySecret + app.AliyunClound.Region = engine.Region } @@ -521,42 +523,65 @@ func AliyunAudioResultMakeSubtitleFile(app *VideoSrt , video string , outputType _,_ = file.WriteString("[ar:]\r\n[ti:]\r\n[al:]\r\n[by:]\r\n") } - + //主字幕 bilingualAsc := app.TranslateCfg.OutputMainSubtitleInputLanguage - index := 0 + + //普通文本容器 + var txtOutputContent bytes.Buffer + var txtTransalteOutputContent bytes.Buffer + for _ , data := range result { var linestr string - //拼接文本 - if outputType == OUTPUT_SRT { - if app.TranslateCfg.TranslateSwitch { - if app.TranslateCfg.BilingualSubtitleSwitch { - linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.Text , data.TranslateText , true , bilingualAsc) + //字幕、歌词文件处理 + if outputType == OUTPUT_SRT || outputType == OUTPUT_LRC { + //拼接 + if outputType == OUTPUT_SRT { + if app.TranslateCfg.TranslateSwitch { + if app.TranslateCfg.BilingualSubtitleSwitch { + linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.Text , data.TranslateText , true , bilingualAsc) + } else { + linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.TranslateText , "" , false , true) + } } else { - linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.TranslateText , "" , false , true) + linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.Text , "" , false , true) + } + } else if outputType == OUTPUT_LRC { + if app.TranslateCfg.TranslateSwitch { + linestr = MakeMusicLrcText(index , data.BeginTime , data.EndTime , data.TranslateText) + } else { + linestr = MakeMusicLrcText(index , data.BeginTime , data.EndTime , data.Text) } - } else { - linestr = MakeSubtitleText(index , data.BeginTime , data.EndTime , data.Text , "" , false , true) } - } else if outputType == OUTPUT_STRING { - if app.TranslateCfg.TranslateSwitch { - linestr = MakeText(index , data.BeginTime , data.EndTime , data.TranslateText) - } else { - linestr = MakeText(index , data.BeginTime , data.EndTime , data.Text) + + //写入行 + if _, e = file.WriteString(linestr);e != nil { + panic(e) } - } else if outputType == OUTPUT_LRC { + } else if outputType == OUTPUT_STRING { + //普通文本处理 + txtOutputContent.WriteString(data.Text) + txtOutputContent.WriteString("\r\n") + if app.TranslateCfg.TranslateSwitch { - linestr = MakeMusicLrcText(index , data.BeginTime , data.EndTime , data.TranslateText) - } else { - linestr = MakeMusicLrcText(index , data.BeginTime , data.EndTime , data.Text) + txtTransalteOutputContent.WriteString(data.TranslateText) + txtTransalteOutputContent.WriteString("\r\n") } } - if _, e = file.WriteString(linestr);e != nil { + index++ + } + + //写入文本文件 + if outputType == OUTPUT_STRING { + txtOutputContent.WriteString("\r\n\r\n\r\n\r\n\r\n") + if _, e = file.WriteString(txtOutputContent.String());e != nil { + panic(e) + } + if _, e = file.WriteString(txtTransalteOutputContent.String());e != nil { panic(e) } - index++ } } } \ No newline at end of file diff --git a/main.go b/main.go index 13c14cf..ea95898 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( ) //应用版本号 -const APP_VERSION = "0.2.9" +const APP_VERSION = "0.2.9.2" var AppRootDir string var mw *MyMainWindow @@ -258,7 +258,7 @@ func main() { }, }, Menu{ - Text: "帮助/支持", + Text: "帮助文档/支持", Image: "./data/img/about.png", Items: []MenuItem{ Action{ @@ -674,8 +674,8 @@ func main() { return } //校验输入语言 - if tempAppSetting.InputLanguage != LANGUAGE_ZH && tempAppSetting.InputLanguage != LANGUAGE_EN { - mw.NewErrormationTips("错误" , "由于语音提供商的限制,生成字幕的输入语言仅支持中文/英语") + if tempAppSetting.InputLanguage == LANGUAGE_KOR { + mw.NewErrormationTips("错误" , "由于语音提供商的限制,生成字幕允许的输入语言目前不支持韩语") return }