diff --git a/README.md b/README.md index 16f861c..6efdda4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ 这是一个可以识别视频语音自动生成字幕SRT文件的开源软件工具。
适用于快速、批量的为媒体(视频/音频)生成中/英文字幕、文本文件的业务场景。 -0.3.2 版本将会使用以下接口: +0.3.3 版本将会使用以下接口: - 阿里云 [OSS对象存储](https://www.aliyun.com/product/oss?spm=5176.12825654.eofdhaal5.13.e9392c4aGfj5vj&aly_as=K11FcpO8) - 阿里云 [录音文件识别](https://ai.aliyun.com/nls/filetrans?spm=5176.12061031.1228726.1.47fe3cb43I34mn) - 百度翻译开放平台 [翻译API](http://api.fanyi.baidu.com/api/trans/product/index) @@ -55,8 +55,8 @@ B站Up主自制教程:[https://search.bilibili.com/all?keyword=videosrt](https ##### 下载地址: -- (v0.3.2)(含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.3.2/video-srt-gui-ffmpeg-0.3.2-x64.zip) -- (v0.3.2)(不含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.3.2/video-srt-gui-0.3.2-x64.zip) +- (v0.3.3)(含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.3.3/video-srt-gui-ffmpeg-0.3.3-x64.zip) +- (v0.3.3)(不含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.3.3/video-srt-gui-0.3.3-x64.zip) - (v0.2.6)(含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.2.6/video-srt-gui-ffmpeg-0.2.6-x64.zip) - (v0.2.6)(不含ffmpeg依赖) [点我下载](http://file.viggo.site/video-srt/0.2.6/video-srt-gui-0.2.6-x64.zip) @@ -75,6 +75,16 @@ B站Up主自制教程:[https://search.bilibili.com/all?keyword=videosrt](https - 然后用旧版本软件的 `data` 文件夹覆盖新版软件的 `data` 文件夹 - 0.2.6 升级至 0.2.9 以上的版本时,由于翻译设置无法直接兼容低版本,可能需要重新在软件创建翻译引擎才能继续使用翻译功能 +## 其他 +今日,有小伙伴在淘宝、闲鱼上发现一些界面相似的盗版且额外收费的软件。由于`VideoSrt` 是开源软件,所以不排除个别不良用户通过微调软件源代码,然后进行二次售卖甚至传播病毒。 + +目前已知的有:`大象字幕` + +因此,软件的安装包不要在第三方平台渠道下载,尽量在 github/码云/帮助文档 等官方渠道的页面进行下载。 + +小伙伴们要擦亮眼睛,打击盗版,望周知! + + ## FAQ ##### 1.为什么Linux和Mac不能用? 因为`VideoSrt`的GUI是使用[lxn/walk](https://github.com/lxn/walk)开发的,仅支持Windows的GUI,如果您想在Linux上使用,可以体验[CLI版本](https://github.com/wxbool/video-srt) diff --git a/app/aliyun/engine.go b/app/aliyun/engine.go index a626672..4651b8d 100644 --- a/app/aliyun/engine.go +++ b/app/aliyun/engine.go @@ -3,9 +3,9 @@ package aliyun import ( "encoding/json" "errors" - "fmt" "github.com/aliyun/alibaba-cloud-sdk-go/sdk" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" "strconv" "time" ) @@ -66,14 +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" + +//是否打开ITN,中文数字将转为阿拉伯数字输出,默认值为false +const KEY_ENABLE_INVERSE_TEXT_NORMAL = "enable_inverse_text_normalization" +//是否启⽤语义断句,取值:true/false,默认值false +const KEY_ENABLE_SEMANTIC_SENTENCE_DETECTION = "enable_semantic_sentence_detection" +//是否启用时间戳校准功能,取值:true/false,默认值false +const KEY_ENABLE_TIMESTAMP_ALIGNMENT = "enable_timestamp_alignment" + // 响应参数key const KEY_TASK string = "Task" const KEY_TASK_ID string = "TaskId" @@ -90,8 +90,6 @@ const STATUS_QUEUEING string = "QUEUEING" func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , error) { 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 @@ -114,10 +112,10 @@ func (c AliyunClound) NewAudioFile(fileLink string) (string , *sdk.Client , erro // 设置是否输出词信息,默认为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" + //统一后处理 + mapTask[KEY_ENABLE_INVERSE_TEXT_NORMAL] = "true" + mapTask[KEY_ENABLE_SEMANTIC_SENTENCE_DETECTION] = "true" + mapTask[KEY_ENABLE_TIMESTAMP_ALIGNMENT] = "true" // to json task, err := json.Marshal(mapTask) @@ -158,7 +156,7 @@ 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 { +func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , logOutput func(text string) , callback func(result []byte)) (err error) { _, domain, apiVersion, product := c.GetApiVariable() getRequest := requests.NewCommonRequest() @@ -170,27 +168,44 @@ func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , ca getRequest.QueryParams[KEY_TASK_ID] = taskId statusText := "" + + var ( + trys = 0 + getResponse *responses.CommonResponse + getResponseContent string + ) + //遍历获取识别结果 - for true { - getResponse, err := client.ProcessCommonRequest(getRequest) + for trys < 10 { + + if trys != 0 { + logOutput("尝试重新查询识别结果,第" + strconv.Itoa(trys) + "次") + } + + getResponse, err = client.ProcessCommonRequest(getRequest) if err != nil { - return err + logOutput("查询识别结果失败:" + err.Error()) + trys++ + time.Sleep(time.Second * time.Duration(trys)) + continue } - getResponseContent := getResponse.GetHttpContentString() + getResponseContent = getResponse.GetHttpContentString() if (getResponse.GetHttpStatus() != 200) { - return errors.New("识别结果查询请求失败 , Http错误码 : " + strconv.Itoa(getResponse.GetHttpStatus())) + logOutput("查询识别结果失败,Http错误码:" + strconv.Itoa(getResponse.GetHttpStatus())) + trys++ + time.Sleep(time.Second * time.Duration(trys)) + continue } var getMapResult map[string]interface{} err = json.Unmarshal([]byte(getResponseContent), &getMapResult) if err != nil { - return err + trys++ + logOutput("查询识别结果失败,解析结果失败:" + err.Error()) + continue } - //调用回调函数 - callback(getResponse.GetHttpContentBytes()) - //校验遍历条件 statusText = getMapResult[KEY_STATUS_TEXT].(string) if statusText == STATUS_RUNNING || statusText == STATUS_QUEUEING { @@ -200,11 +215,14 @@ func (c AliyunClound) GetAudioFileResult(taskId string , client *sdk.Client , ca } } - if statusText != STATUS_SUCCESS { - return errors.New("录音文件识别失败 , (" + c.GetErrorStatusTextMessage(statusText) + ")") + if statusText == STATUS_SUCCESS && getResponse != nil { + //调用回调函数 + callback(getResponse.GetHttpContentBytes()) + } else { + err = errors.New("录音文件识别失败 , (" + c.GetErrorStatusTextMessage(statusText) + ")") + return } - - return nil + return } diff --git a/app/ffmpeg/ffmpeg.go b/app/ffmpeg/ffmpeg.go index 2017dd3..a9646b2 100644 --- a/app/ffmpeg/ffmpeg.go +++ b/app/ffmpeg/ffmpeg.go @@ -44,7 +44,6 @@ func VailFfmpegLibrary() error { //校验ffmpeg并加入临时环境遍历 func VailTempFfmpegLibrary(rootDir string) { ffmpegDir := tool.WinDir(rootDir + "/ffmpeg") - //fmt.Println("VailTempFfmpegLibrary " , ffmpegDir) if tool.DirExists(ffmpegDir) { //临时加入用户环境变量 diff --git a/app/tool/tool.go b/app/tool/tool.go index 06680cd..e6e6dbd 100644 --- a/app/tool/tool.go +++ b/app/tool/tool.go @@ -167,7 +167,7 @@ func MusicLrcTextMillisecond(time int64) string { var minText = RepeatStr(strconv.FormatInt(min , 10) , "0" , 2 , true) var millisecondText = RepeatStr(strconv.FormatInt(millisecond , 10) , "0" , 2 , true) - return minText + ":" + miaoText + ":" + millisecondText + return minText + ":" + miaoText + "." + millisecondText } diff --git a/app/video.go b/app/video.go index c0df676..4d1a195 100644 --- a/app/video.go +++ b/app/video.go @@ -234,7 +234,7 @@ func (app *VideoSrt) Run(video string) { } //阿里云录音文件识别 - AudioResult , IntelligentBlockResult := AliyunAudioRecognition(app , app.AliyunClound, filelink) + AudioResult , IntelligentBlockResult := AliyunAudioRecognition(app , video , app.AliyunClound, filelink) app.Log("文件识别成功 , 字幕处理中 ..." , video) @@ -398,7 +398,7 @@ func CheckEmptyResult(AudioResult map[int64][] *aliyun.AliyunAudioRecognitionRes //阿里云录音文件识别 -func AliyunAudioRecognition(app *VideoSrt , engine aliyun.AliyunClound , filelink string) (AudioResult map[int64][] *aliyun.AliyunAudioRecognitionResult , IntelligentBlockResult map[int64][] *aliyun.AliyunAudioRecognitionResult) { +func AliyunAudioRecognition(app *VideoSrt , video string , engine aliyun.AliyunClound , filelink string) (AudioResult map[int64][] *aliyun.AliyunAudioRecognitionResult , IntelligentBlockResult map[int64][] *aliyun.AliyunAudioRecognitionResult) { //创建识别请求 taskid, client, e := engine.NewAudioFile(filelink) if e != nil { @@ -409,9 +409,10 @@ func AliyunAudioRecognition(app *VideoSrt , engine aliyun.AliyunClound , filelin IntelligentBlockResult = make(map[int64][] *aliyun.AliyunAudioRecognitionResult) //遍历获取识别结果 - resultError := engine.GetAudioFileResult(taskid , client , func(result []byte) { - //mylog.WriteLog(string(result)) - + resultError := engine.GetAudioFileResult(taskid , client , func(text string) { + //日志输出 + app.Log(text , video) + } , func(result []byte) { //结果处理 statusText, _ := jsonparser.GetString(result, "StatusText") //结果状态 diff --git a/main.go b/main.go index 6f0b690..d77171d 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( ) //应用版本号 -const APP_VERSION = "0.3.2" +const APP_VERSION = "0.3.3" var AppRootDir string var mw *MyMainWindow @@ -310,6 +310,12 @@ func main() { _ = tool.OpenUrl("https://www.mu-yan.net/") }, }, + Menu{ + Text: "实时字幕小工具", + OnTriggered: func() { + _ = tool.OpenUrl("https://gitee.com/641453620/livecaption") + }, + }, }, }, Size: Size{800, 650}, @@ -769,17 +775,6 @@ func main() { mw.NewErrormationTips("错误" , "请先设置Oss对象配置") return } - //校验输入语言 - if tempAppSetting.InputLanguage != LANGUAGE_ZH && - tempAppSetting.InputLanguage != LANGUAGE_EN && - tempAppSetting.InputLanguage != LANGUAGE_JP && - tempAppSetting.InputLanguage != LANGUAGE_KOR && - tempAppSetting.InputLanguage != LANGUAGE_RU && - tempAppSetting.InputLanguage != LANGUAGE_SPA { - mw.NewErrormationTips("错误" , "由于语音提供商的限制,生成字幕仅支持中文、英文、日语、韩语、俄语、西班牙语") - return - } - //查询选择的语音引擎 if tempAppSetting.CurrentEngineId == 0 { mw.NewErrormationTips("错误" , "请先新建/选择语音引擎")