├── .github └── workflows │ └── release.yml ├── CHANGELOG.md ├── README.md ├── go.mod ├── go.sum ├── main.go ├── mp3 └── ListenMe.mp3 └── tts.config /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - 'CHANGELOG.md' 9 | 10 | jobs: 11 | 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Set up Go 18 | uses: actions/setup-go@v3 19 | with: 20 | go-version: 1.18 21 | 22 | - name: Get TAG 23 | run: | 24 | echo "tts_tag=$(sed -n '1p' CHANGELOG.md)" >> $GITHUB_ENV 25 | sed -i '1d' CHANGELOG.md 26 | 27 | - name: Go build 28 | run: | 29 | mkdir release 30 | GOOS=darwin GOARCH=amd64 go build -o ./release/${{env.tts_tag}}_mac_amd64 31 | GOOS=windows GOARCH=amd64 go build -o ./release/${{env.tts_tag}}_windowns_amd64 32 | GOOS=linux GOARCH=amd64 go build -o ./release/${{env.tts_tag}}_linux_amd64 33 | GOOS=linux GOARCH=arm64 go build -o ./release/${{env.tts_tag}}_linux_arm64 34 | GOOS=android GOARCH=arm64 go build -o ./release/${{env.tts_tag}}_termux_arm64 35 | ls ./release/ 36 | 37 | - name: Upload App To Artifact 38 | uses: actions/upload-artifact@v3 39 | with: 40 | name: ${{env.tts_tag}} 41 | path: ${{ github.workspace }}/release/* 42 | 43 | - name: Release 44 | uses: softprops/action-gh-release@cd28b0f5ee8571b76cfdaa62a30d51d752317477 45 | with: 46 | name: ${{ env.tts_tag }} 47 | tag_name: ${{ env.tts_tag }} 48 | body_path: ${{ github.workspace }}/CHANGELOG.md 49 | draft: false 50 | prerelease: false 51 | files: ${{ github.workspace }}/release/* 52 | env: 53 | GITHUB_TOKEN: ${{ secrets.TOKEN }} 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | tts_v0.1.65 2 | 3 | 修改bug 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 微软官网只有试听功能,本程序可以下载音频文件 2 | 3 | ## 如何使用? 4 | 5 | 1. 下载源代码使用 6 | 7 | ``` 8 | git clone https://github.com/asters1/tts 9 | 10 | cd tts 11 | 12 | go run main.go 13 | ``` 14 | 15 | 2. 或者直接下载已经编译好的文件(需要配置tts.config文件) 16 | 注:似乎交叉编译有问题,自己下载源码,自己编译吧! 17 | 18 | 19 | 3. tts.config(需要将此文件放置到tts同一目录下,并且新建一个名字为mp3的文件夹。否则会报错!!) 20 | 21 | 22 | ``` 23 | #此配置文件以#号作为注释 24 | # 25 | # 26 | # 27 | # 28 | #语言默认为zh-CN 29 | Language:zh-CN 30 | 31 | #Name为发音员,默认为XiaoxiaoNeural 32 | 33 | #发音员不止以下几个,懒得写了。自己找,网址为: 34 | #https://azure.microsoft.com/zh-cn/services/cognitive-services/text-to-speech/#overview 35 | 36 | 37 | #Name:XiaoxiaoNeural 38 | #XiaoxiaoNeural #晓晓 39 | #XiaoyouNeural #晓悠 40 | Name:YunxiNeural #云希 41 | #-SC-YunxiNeural #四川云希 42 | # 43 | 44 | #volume为音量,默认为100,区间[0,100] 45 | volume:100 46 | 47 | #rate为语速,默认为0,区间[-100,200] 48 | rate:0 49 | 50 | #pitch为音调,默认为0,区间[-50,50] 51 | pitch:0 52 | 53 | #path为保存音频路径,默认为当前目录下的mp3文件目录下 54 | path:./mp3/ 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module tts 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/asters1/tools v0.1.5 7 | github.com/gorilla/websocket v1.5.0 8 | ) 9 | 10 | require ( 11 | github.com/satori/go.uuid v1.2.0 // indirect 12 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/asters1/tools v0.1.5 h1:fFwRfAsNmcSnesQRdBUvQWaal9PAnqttvewLKgHY1L0= 2 | github.com/asters1/tools v0.1.5/go.mod h1:ZRDA5r2/iosXc0r+5o5BAt+zrTTP6lMltD/6yHBF2Wo= 3 | github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= 4 | github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 5 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 6 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 7 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 8 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 9 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 10 | github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= 11 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 12 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 13 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 14 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "strconv" 9 | "strings" 10 | "time" 11 | 12 | "github.com/asters1/tools" 13 | "github.com/gorilla/websocket" 14 | ) 15 | 16 | func GetISOTime() string { 17 | T := time.Now().String() 18 | return T[:23][:10] + "T" + T[:23][11:] + "Z" 19 | 20 | } 21 | func GetLocalTime() string { 22 | BJ, _ := time.LoadLocation("Asia/Shanghai") 23 | T := time.Now().In(BJ).String() 24 | return T[:23][:10] + "_" + T[:19][11:] 25 | 26 | } 27 | 28 | func main() { 29 | config, _ := tools.GetConfig("./tts.config") 30 | fmt.Println("获取uuid...") 31 | uuid := tools.GetUUID() 32 | 33 | WssUrl := `wss://eastus.api.speech.microsoft.com/cognitiveservices/websocket/v1?TricType=AzureDemo&Authorization=bearer%20undefined&X-ConnectionId=` + uuid 34 | 35 | dl := websocket.Dialer{ 36 | EnableCompression: true, 37 | } 38 | 39 | fmt.Println("创建websocket连接...") 40 | conn, _, err := dl.Dial(WssUrl, tools.GetHeader( 41 | `Accept-Encoding:gzip 42 | User-Agent:Mozilla/5.0 (Linux; Android 7.1.2; M2012K11AC Build/N6F26Q; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.117 Mobile Safari/537.36 43 | Origin:https://azure.microsoft.com`, 44 | )) 45 | if err != nil { 46 | fmt.Println("websocket连接失败") 47 | } 48 | defer conn.Close() 49 | 50 | m1 := "Path: speech.config\r\nX-RequestId: " + uuid + "\r\nX-Timestamp: " + GetISOTime() + "\r\nContent-Type: application/json\r\n\r\n{\"context\":{\"system\":{\"name\":\"SpeechSDK\",\"version\":\"1.19.0\",\"build\":\"JavaScript\",\"lang\":\"JavaScript\",\"os\":{\"platform\":\"Browser/Linux x86_64\",\"name\":\"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0\",\"version\":\"5.0 (X11)\"}}}}" 51 | m2 := "Path: synthesis.context\r\nX-RequestId: " + uuid + "\r\nX-Timestamp: " + GetISOTime() + "\r\nContent-Type: application/json\r\n\r\n{\"synthesis\":{\"audio\":{\"metadataOptions\":{\"sentenceBoundaryEnabled\":false,\"wordBoundaryEnabled\":false},\"outputFormat\":\"audio-24khz-160kbitrate-mono-mp3\"}}}" 52 | conn.WriteMessage(websocket.TextMessage, []byte(m1)) 53 | conn.WriteMessage(websocket.TextMessage, []byte(m2)) 54 | for { 55 | fmt.Println("请输入文本内容:(退出请输入q,然后回车)") 56 | readers := bufio.NewReader(os.Stdin) 57 | 58 | text, _, _ := readers.ReadLine() 59 | if string(text) == "q" { 60 | break 61 | } 62 | SSML := ` 63 | 64 | 65 | ` + string(text) + ` 66 | 67 | 68 | ` 69 | m3 := "Path: ssml\r\nX-RequestId: " + tools.GetUUID() + "\r\nX-Timestamp: " + GetISOTime() + "\r\nContent-Type: application/ssml+xml\r\n\r\n" + SSML 70 | conn.WriteMessage(websocket.TextMessage, []byte(m3)) 71 | 72 | var Adata []byte 73 | fmt.Println("正在下载文件...") 74 | for { 75 | Num, message, err := conn.ReadMessage() 76 | if err != nil { 77 | fmt.Println(err) 78 | break 79 | } 80 | if Num == 2 { 81 | index := strings.Index(string(message), "Path:audio") 82 | 83 | data := []byte(string(message)[index+12:]) 84 | Adata = append(Adata, data...) 85 | } else if Num == 1 && string(message)[len(string(message))-14:len(string(message))-6] == "turn.end" { 86 | fmt.Println("已完成") 87 | break 88 | } 89 | 90 | } 91 | Adata = Adata[:len(Adata)-2400] 92 | fmt.Println("文件存放路径为:" + config["path"] + config["Language"] + "-" + config["Name"] + "-" + GetLocalTime() + ".mp3") 93 | ioutil.WriteFile(config["path"]+config["Language"]+"-"+config["Name"]+"-"+strconv.Itoa(int(time.Now().Unix()))+".mp3", Adata, 0666) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /mp3/ListenMe.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asters1/tts/ca020dd367912406ebd6769c7402a3ed42fd6442/mp3/ListenMe.mp3 -------------------------------------------------------------------------------- /tts.config: -------------------------------------------------------------------------------- 1 | #此配置文件以#号作为注释 2 | # 3 | # 4 | # 5 | # 6 | #语言默认为zh-CN 7 | Language:zh-CN 8 | 9 | #Name为发音员,默认为XiaoxiaoNeural 10 | #Name:XiaoxiaoNeural 11 | #XiaoxiaoNeural #晓晓 12 | #XiaoyouNeural #晓悠 13 | Name:YunxiNeural #云希 14 | #-SC-YunxiNeural #云希 15 | # 16 | 17 | #volume为音量,默认为100,区间[0,100] 18 | volume:100 19 | 20 | #rate为语速,默认为0,区间[-100,200] 21 | rate:0 22 | 23 | #pitch为音调,默认为0,区间[-50,50] 24 | pitch:0 25 | 26 | #path为保存音频路径,默认为当前目录下的mp3文件目录下 27 | path:./mp3/ 28 | 29 | --------------------------------------------------------------------------------