日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

WebSocket協議說明

本文介紹如何使用智能語音交互流式文本WebSocket協議使用語音合成。如果您不希望引入阿里云智能語音交互產品SDK,或者目前提供的SDK不能滿足您的要求,可以基于本文描述自行開發代碼訪問阿里語音服務。

前提條件

在使用WebSocket協議對接之前,請先閱讀API詳情中的服務交互流程說明 。

鑒權

服務端通過臨時Token進行鑒權,請求時需要在URL中攜帶Token參數,Token獲取方式請參見獲取Token概述。獲取Token之后通過如下方式訪問語音服務端。

訪問類型

說明

URL

外網訪問(默認北京地域)

所有服務器均可使用外網訪問URL(SDK中默認設置了外網訪問URL)。

北京:wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1

ECS內網訪問

使用阿里云北京ECS(即ECS地域為華北2(北京)),可使用內網訪問URL。 ECS的經典網絡不能訪問AnyTunnel,即不能在內網訪問語音服務;如果希望使用AnyTunnel,需要創建專有網絡在其內部訪問。

說明

使用內網訪問方式,將不產生ECS實例的公網流量費用。

關于ECS的網絡類型請參見網絡類型

北京:ws://nls-gateway-cn-beijing-internal.aliyuncs.com:80/ws/v1

請求指令

請求指令用于控制語音識別任務的起止,標識任務邊界,以JSON格式的Text Frame方式發送服務端請求,需要在Header中設置請求的基礎信息。指令由Header和Payload兩部分組成,其中Header部分為統一格式,不同指令的Payload部分格式各不相同。

1. Header格式說明

Header格式如下:

參數

類型

是否必選

說明

header

請求頭

-

-

header.appkey

String

管控臺創建的項目Appkey。

header.message_id

String

當次消息請求ID,隨機生成32位唯一ID。

header.task_id

String

整個實時語音合成的會話ID,整個請求中需要保持一致,32位唯一ID。

header.namespace

String

訪問的產品名稱,固定為“FlowingSpeechSynthesizer”。

header.name

String

指令名稱,包含StartSynthesis和StopSynthesis指令。

2. StartSynthesis指令

參數

類型

是否必選

說明

payload.voice

String

發音人,默認是longxiaochun。發音人,默認是longxiaochun。

payload.format

String

音頻編碼格式,支持pcm、wav和mp3格式,默認值:pcm。音頻編碼格式,支持pcm、wav和mp3格式,默認值:pcm。

payload.sample_rate

Integer

音頻采樣率,默認值:16000Hz。

payload.volume

Integer

音量,取值范圍:0~100。默認值:50。

payload.speech_rate

Integer

語速,取值范圍:-500~500,默認值:0。

[-500,0,500]對應的語速倍速區間為 [0.5,1.0,2.0]。

payload.pitch_rate

Integer

語調,取值范圍:-500~500,默認值:0。

payload.enable_subtitle

Boolean

開啟字級別時間戳。

payload.enable_phoneme_timestamp

Boolean

開啟音素級別時間戳。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "StartSynthesis",
        "appkey": "17d4c634****"
    },
    "payload": {
        "voice": "longxiaochun",
        "format": "wav",
        "sample_rate": 16000,
        "volume": 50,
        "speech_rate": 0,
        "pitch_rate": 0,
        "enable_subtitle": true
    }
}

3. RunSynthesis指令

參數

類型

是否必選

說明

text

String

需要合成的文本

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "RunSynthesis",
        "appkey": "17d4c634****"
    },
    "payload": {
        "text": "流式輸入文本"
    }
}

4. StopSynthesis指令

StopSynthesis指令要求服務端停止語音合成,并且合成所有緩存文本。

重要

由于流式文本語音合成服務端會分句合成音頻,因此服務端存在未滿足分句條件的緩存文本,需要在文本流發送結束后立刻發送此指令,否則有可能丟失文本。

Payload為空。示例代碼如下:

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "StopSynthesis",
        "appkey": "17d4c634****"
    }
}

下行數據

WebSocket 數據幀分為文本幀 (text frame)、二進制幀 (binary frame)、關閉幀 (close frame)、Ping幀 和 Pong幀。我們使用文本幀下發事件,使用二進制幀下發音頻數據流。

以python中的websocket-client為例,可以參考下述示例代碼解析WebSocket收到的數據:

audio_data = None


# 監聽消息的回調函數
def on_message(self, ws, message):
    if isinstance(message, str):
        # 將文本幀解析為json
        try:
            json_data = json.loads(message)
            # TODO: 解析事件
        except json.JSONDecodeError:
            print("Failed to parse message as JSON.")
    elif isinstance(message, (bytes, bytearray)):
        # 將二進制幀作為音頻幀保存
        # TODO: 保存音頻或使用支持流式輸入的播放器播放,例如pyaudio
        if audio_data is None:
            audio_data = bytes(message)
        else:
            audio_data = self._audio_data + bytes(message)

ws = websocket.WebSocketApp(
    url,
    header={
        "X-NLS-Token": token,
    },
    on_message=on_message,
    on_error=None,
    on_close=None,
)

關于Websocket詳細介紹可以參考鏈接

事件

事件指的是服務端返回給客戶端的處理進度事件,代表不同的處理階段,客戶端可獲取不同處理階段的事件實現不同的業務邏輯。以JSON格式返回,事件由Header和Payload兩部分組成,其中Header部分為統一格式,不同事件的Payload部分格式可能不同。

1. SynthesisStarted事件

參數

類型

說明

session_id

String

客戶端請求時傳入session_id的話則原樣返回,否則由服務端自動生成32位唯一ID。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "SynthesisStarted",
        "status": 20000000,
        "status_message": "GATEWAY|SUCCESS|Success."
    },
    "payload": {
        "session_id": "1231231dfdf****"
    }

2. SentenceBegin事件

SentenceBegin事件表示服務端檢測到了一句話的開始。

參數

類型

說明

index

Integer

句子編號,從1開始遞增。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "SentenceBegin",
        "status": 20000000,
        "status_message": "GATEWAY|SUCCESS|Success."
    },
    "payload": {
        "index": 1
    }
}

3. SentenceSynthesis事件

SentenceSynthesis事件表示有新的合成結果返回,包含最新的音頻和時間戳,句內全量,句間增量。

參數

類型

說明

subtitles[]

ArrayList

時間戳信息。

subtitles[0].text

String

?本信息。

subtitles[0].sentence

String

句子時間戳控制,True表示當前時間戳為句子。

subtitles[0].begin_index

Integer

該字在整句中的開始位置,從0開始。

subtitles[0].end_index

Integer

該字在整句中的結束位置,從0開始。

subtitles[0].begin_time

Integer

?本對應TTS語?開始時間戳,單位ms。

subtitles[0].end_time

Integer

?本對應TTS語?結束時間戳,單位ms。

subtitles[0].phoneme_list

ArrayList

文本的音素時間戳信息。

subtitles[0].phoneme_list[0].index

Integer

該音素的下標,從0開始。

subtitles[0].phoneme_list[0].beginTime

Integer

該音素對應TTS語音開始時間戳,單位ms。

subtitles[0].phoneme_list[0].endTime

Integer

該音素對應TTS語音結束時間戳,單位ms。

subtitles[0].phoneme_list[0].phoneme

String

音素信息。

subtitles[0].phoneme_list[0].tone

String

語氣信息。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "SentenceSynthesis",
        "status": 20000000,
        "status_message": "GATEWAY|SUCCESS|Success."
    },
    "payload": {
        "subtitles": [
            {
                "text": "",
                "begin_time": 0,
                "end_time": 0,
                "begin_index": 0,
                "end_index": 1,
                "sentence": true,
                "phoneme_list": []
            },
            {
                "text": "今",
                "begin_time": 0,
                "end_time": 175,
                "begin_index": 0,
                "end_index": 1,
                "sentence": false,
                "phoneme_list": [
                    {
                        "begin_time": 0,
                        "end_time": 120,
                        "text": "j_c",
                        "tone": "1"
                    },
                    {
                        "begin_time": 120,
                        "end_time": 170,
                        "text": "in_c",
                        "tone": "1"
                    }
                ]
            }
        ]
    }
}

4. SentenceEnd事件

SentenceEnd事件表示服務端檢測到了一句話的結束,返回該句的全量時間戳。

參數

類型

說明

subtitles[]

ArrayList

時間戳信息。

subtitles[0].text

String

?本信息。

subtitles[0].sentence

String

句子時間戳控制,True表示當前時間戳為句子。

subtitles[0].begin_index

Integer

該字在整句中的開始位置,從0開始。

subtitles[0].end_index

Integer

該字在整句中的結束位置,從0開始。

subtitles[0].begin_time

Integer

?本對應TTS語?開始時間戳,單位ms。

subtitles[0].end_time

Integer

?本對應TTS語?結束時間戳,單位ms。

subtitles[0].phoneme_list

ArrayList

文本的音素時間戳信息。

subtitles[0].phoneme_list[0].index

Integer

該音素的下標,從0開始。

subtitles[0].phoneme_list[0].beginTime

Integer

該音素對應TTS語音開始時間戳,單位ms。

subtitles[0].phoneme_list[0].endTime

Integer

該音素對應TTS語音結束時間戳,單位ms。

subtitles[0].phoneme_list[0].phoneme

String

音素信息。

subtitles[0].phoneme_list[0].tone

String

語氣信息。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "SentenceEnd",
        "status": 20000000,
        "status_message": "GATEWAY|SUCCESS|Success."
    },
    "payload": {
        "subtitles": [
            {
                "text": "",
                "begin_time": 0,
                "end_time": 0,
                "begin_index": 0,
                "end_index": 1,
                "sentence": true,
                "phoneme_list": []
            },
            {
                "text": "今",
                "begin_time": 0,
                "end_time": 175,
                "begin_index": 0,
                "end_index": 1,
                "sentence": false,
                "phoneme_list": [
                    {
                        "begin_time": 0,
                        "end_time": 120,
                        "text": "j_c",
                        "tone": "1"
                    },
                    {
                        "begin_time": 120,
                        "end_time": 170,
                        "text": "in_c",
                        "tone": "1"
                    }
                ]
            },
            {
                "text": "天",
                "begin_time": 175,
                "end_time": 320,
                "begin_index": 1,
                "end_index": 2,
                "sentence": false,
                "phoneme_list": [
                    {
                        "begin_time": 0,
                        "end_time": 120,
                        "text": "t_c",
                        "tone": "1"
                    },
                    {
                        "begin_time": 120,
                        "end_time": 170,
                        "text": "ian_c",
                        "tone": "1"
                    }
                ]
            }
        ]
    }
}

5. SynthesisCompleted事件

SynthesisCompleted事件表示服務端已停止了語音合成并且所有音頻數據下發完畢。

{
    "header": {
        "message_id": "05450bf69c53413f8d88aed1ee60****",
        "task_id": "640bc797bb684bd6960185651307****",
        "namespace": "FlowingSpeechSynthesizer",
        "name": "SynthesisCompleted",
        "status": 20000000,
        "status_message": "GATEWAY|SUCCESS|Success."
    },
    "payload": {
        "measureType": "TextLengthHD",
        "measureLength": 57
    }    
}

下行音頻流

在流式語音合成中,音頻會以數據流的方式分幀下發。下發的所有音頻為一個完整的音頻文件,可以通過支持流式播放的播放器,例如:ffmpeg、pyaudio (Python)、AudioFormat (Java)、MediaSource (Javascript)等,實時播放。

重要
  1. 從第一次發起RunSynthesis指令發送文本開始,到收到SynthesisCompleted之間會收到音頻流。

  2. 在流式語音合成中,是將一個完整的音頻文件分多次返回。在播放流式音頻時,需要使用支持流式播放的音頻播放器,而不是將每一幀當作一個獨立的音頻播放,這樣無法成功解碼。

  3. 在保存音頻時,請使用追加模式寫入同一個文件。

  4. 在使用wav/mp3格式合成音頻時,由于文件按照流式合成,因此只在第一幀中包含當前任務的文件頭信息。

JavaScript示例代碼

可以參考 流式語音合成JS示例 使用JavaScript實現流式語音合成協議并播放。

請在打開demo.html前首先替換app.js中的appkey和token,并且將voice參數替換為cosyvoice大模型音色。之后可以點擊demo.html網頁中的按鈕發送對應指令。在一次流程中,RunSynthesis可以點擊多次。

interface.png

播放器說明

播放邏輯集中在 app.js中的 connectAndStartSynthesis 函數中,主要步驟如下:

  1. 在網頁中添加audio標簽的player用于播放音頻。

  2. 創建一個 MediaSource 對象,它用于動態生成音頻流。設置播放器的源為MediaSource對象,并且通過sourceopen事件啟動player開始播放。

  3. 為MediaSource 創建 SourceBuffer,用來解碼 mp3 格式的音頻數據。

  4. 當 WebSocket 接收到音頻數據(Blob 類型)時,通過 FileReader 讀取其 ArrayBuffer 并添加到 SourceBuffer。

  5. 在收到SynthesisCompleted事件后結束MediaSource流。

通過上述步驟,確保可以實時播放收到的音頻流,并且正確結束。

測試工具

在根據Websocket協議開發接口過程中,可以下載NlsStreamInputTtsMockServer.py腳本,運行如下命令安裝依賴,并在本地模擬公有云流式語音合成服務進行調試:

pip install websocket-client
python NlsStreamInputTtsMockServer.py

在成功執行腳本后,將默認在本地的 ws://127.0.0.1:12345 運行模擬服務。請在可以成功調用本地的模擬服務后再切換到線上服務調試。