語音合成
支持的領域 / 任務:audio(音頻) / tts(語音合成)。
語音合成提供的實時語音合成API,可將文字內容轉化為音頻。除語音數據外,可選擇開啟字級別和音素級別時間戳,用于生成字幕或驅動數字人嘴型。
不同的使用場景,需要選擇適合的模型,如客服場景、直播場景、方言場景、童聲場景等,詳情請參考模型列表。采樣率的選擇也同樣重要,通常情況下,客服場景建議選擇8kHz,其他場景建議選擇16k/24k/48kHz,采樣率越高音頻越飽滿,聽感越好。
前提條件
已開通服務并獲得API-KEY:API-KEY的獲取與配置。
已安裝最新版SDK:安裝DashScope SDK。
同步調用
提交單個語音合成任務,無需調用回調函數,進行語音合成(無流式輸出中間結果),最終一次性獲取完整結果。
以下示例,展示如何使用同步接口調用發音人模型知廚(sambert-zhichu-v1),將文案“今天天氣怎么樣”合成采樣率為48kHz,音頻格式為wav的音頻,并保存到名為output.wav的文件中。
需要使用您的API-KEY替換示例中的your-dashscope-api-key,代碼才能正常運行。
# coding=utf-8
import dashscope
from dashscope.audio.tts import SpeechSynthesizer
dashscope.api_key = 'your-dashscope-api-key'
result = SpeechSynthesizer.call(model='sambert-zhichu-v1',
text='今天天氣怎么樣',
sample_rate=48000,
format='wav')
if result.get_audio_data() is not None:
with open('output.wav', 'wb') as f:
f.write(result.get_audio_data())
print(' get response: %s' % (result.get_response()))
package com.alibaba.dashscope.sample;
import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisAudioFormat;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Status;
import java.io.*;
import java.nio.ByteBuffer;
public class Main {
public static void SyncAudioDataToFile() {
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("sambert-zhichu-v1")
.text("今天天氣怎么樣")
.sampleRate(48000)
.format(SpeechSynthesisAudioFormat.WAV)
.apiKey("your-dashscope-api-key")
.build();
File file = new File("output.wav");
// 調用call方法,傳入param參數,獲取合成音頻
ByteBuffer audio = synthesizer.call(param);
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(audio.array());
System.out.println("synthesis done!");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
SyncAudioDataToFile();
System.exit(0);
}
}
同步接口將阻塞當前線程,直到合成完成或者出現錯誤。
請求參數說明
參數 | 類型 | 默認值 | 說明 |
model | string | - | 指定用于語音合成的音色模型名,完整列表參考模型列表。 |
text | string | - | 待合成文本,要求采用UTF-8編碼且不能為空,一次性合成最高一萬字符,其中每個漢字、英文、標點符號均按照1個字計算,支持SSML格式。SSML標記語言使用,請點擊SSML標記語言介紹。 |
format | string | WAV | 返回音頻編碼格式,支持PCM/WAV/MP3格式。 |
sample_rate | int | 16000 | 返回音頻采樣率,建議使用模型默認采樣率(參考模型列表),如果不匹配,服務會進行必要的升降采樣處理。 |
volume | int | 50 | 返回音頻音量,取值范圍是0~100。 |
rate | double | 1.0 | 返回音頻語速,取值范圍0.5~2:
|
pitch | double | 1.0 | 返回音頻語調,取值范圍:0.5~2。 |
word_timestamp_enabled | bool | false | 是否開啟字級別時間戳。 |
phoneme_timestamp_enabled | bool | false | 是否在開啟字級別時間戳的基礎上,顯示音素時間戳。 |
返回接口說明
返回結果中包含二進制音頻數據。如果選擇開啟時間戳,還會返回時間戳信息。以Java SDK為例,SpeechSynthesizer類提供如下函數。
方法名 | 方法簽名 | 說明 |
getAudioData | ByteBuffer getAudioData() | 二進制音頻數據。 |
getTimestamps | List<Sentence> getTimestamps() | 多個句級別時間戳信息Sentence的List,時間戳相關類的說明見下文。 |
返回參數時間戳說明
參數 | 類型 | 說明 |
begin_time | int | 句子/詞/音素開始時間,單位為ms。 |
end_time | int | 句子/詞/音素結束時間,單位為ms。 |
words | List[] | 包含的字時間戳信息,需要在請求中將word_timestamp_enabled也設置為true。 |
text | string | 時間戳文本信息。 |
phonemes | List[] | 包含的音素時間戳信息,需要請求中phoneme_timestamp_enabled也設置為true。 |
tone | string | 音調。英文中0/1/2分別代表輕音/重音/次重音。拼音中1/2/3/4/5分別代表一聲/二聲/三聲/四聲/輕聲。 |
流式調用
提交單個語音合成任務,通過回調的方式流式輸出中間結果,合成結果通過ResultCallback中的回調函數流式進行獲取。語音合成成功完成回調后還可以一次性獲取完整的音頻和時間戳結果。
以下示例展示了如何使用流式接口調用發音人模型知廚(sambert-zhichu-v1)將文案“今天天氣怎么樣”合成采樣率為48kHz,默認音頻格式(wav)的流式音頻,并獲取對應時間戳。
調用示例
# coding=utf-8
import dashscope
import sys
from dashscope.api_entities.dashscope_response import SpeechSynthesisResponse
from dashscope.audio.tts import ResultCallback, SpeechSynthesizer, SpeechSynthesisResult
dashscope.api_key = 'your-dashscope-api-key'
class Callback(ResultCallback):
def on_open(self):
print('Speech synthesizer is opened.')
def on_complete(self):
print('Speech synthesizer is completed.')
def on_error(self, response: SpeechSynthesisResponse):
print('Speech synthesizer failed, response is %s' % (str(response)))
def on_close(self):
print('Speech synthesizer is closed.')
def on_event(self, result: SpeechSynthesisResult):
if result.get_audio_frame() is not None:
print('audio result length:', sys.getsizeof(result.get_audio_frame()))
if result.get_timestamp() is not None:
print('timestamp result:', str(result.get_timestamp()))
callback = Callback()
SpeechSynthesizer.call(model='sambert-zhichu-v1',
text='今天天氣怎么樣',
sample_rate=48000,
callback=callback,
word_timestamp_enabled=True,
phoneme_timestamp_enabled=True)
package com.alibaba.dashscope.sample;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Status;
import java.util.concurrent.CountDownLatch;
public class Main {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("sambert-zhichu-v1")
.text("今天天氣怎么樣")
.sampleRate(48000)
.enableWordTimestamp(true)
.enablePhonemeTimestamp(true)
.apiKey("your-dashscope-api-key")
.build();
class ReactCallback extends ResultCallback<SpeechSynthesisResult> {
@Override
public void onEvent(SpeechSynthesisResult result) {
if (result.getAudioFrame() != null) {
// do something with the audio frame
System.out.println("audio result length: " + result.getAudioFrame().array().length);
}
if (result.getTimestamp() != null) {
// do something with the timestamp
System.out.println("tiemstamp: " + result.getTimestamp());
}
}
@Override
public void onComplete() {
// do something when the synthesis is done
System.out.println("onComplete!");
latch.countDown();
}
@Override
public void onError(Exception e) {
// do something when an error occurs
System.out.println("onError:" + e);
latch.countDown();
}
}
synthesizer.call(param, new ReactCallback());
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.exit(0);
}
}
請求參數說明
參數 | 類型 | 默認值 | 說明 |
model | string | - | 指定用于語音合成的音色模型名,完整模型請參考模型列表。 |
text | string | - | 待合成文本,要求采用UTF-8編碼且不能為空,一次性合成最高一萬字符,其中每個漢字、英文、標點符號均按照1個字計算,支持SSML格式。SSML標記語言使用,請點擊SSML標記語言介紹。 |
format | string | WAV | 返回音頻編碼格式,支持PCM/WAV/MP3格式。 |
sample_rate | int | 16000 | 返回音頻采樣率,建議使用模型默認采樣率(參考模型列表),如果不匹配,服務會進行必要的升降采樣處理。 |
volume | int | 50 | 返回音頻音量,取值范圍是0~100。 |
rate | double | 1 | 返回音頻語速,取值范圍0.5~2:
|
pitch | double | 1 | 返回音頻語調,取值范圍:0.5~2。 |
word_timestamp_enabled | bool | false | 是否開啟字級別時間戳。 |
phoneme_timestamp_enabled | bool | false | 是否在開啟字級別時間戳的基礎上,顯示音素時間戳。 |
回調函數說明
以Java SDK為例,流式響應過程中,ResultCallback有如下回調函數可以被重新定義。
方法簽名 | 是否必須override | 說明 |
void onOpen(Status status) | 否 | 當WebSocket建立鏈接完成后立刻會被回調。 |
void onEvent(SpeechSynthesisResult result) | 是 | 當服務有回復時會被回調,SpeechSynthesisResult類型會在后文中介紹。 |
void onComplete() | 否 | 當所有合成數據全部返回后進行回調。 |
void onError(Exception e) | 否 | 當調用過程出現異常以及服務返回錯誤后進行回調。 |
void doClose(Status status) | 否 | 當服務正在關閉連接時進行調用。 |
void onClose(Status status) | 否 | 當服務已經關閉連接后進行回調。 |
返回結果說明
以Java SDK為例,SpeechSynthesisResult代表一次流式合成數據,包含合成音頻片段和對應合成中的文本句級別范圍的時間戳。
SpeechSynthesisResult中getAudioFrame()或getTimestamp()的結果可能為空,這是因為服務的應答數據幀分為binary音頻幀和text時間戳文本幀,兩種幀交替返回到客戶端。
成員方法 | 方法簽名 | 說明 |
getAudioFrame | ByteBuffer getAudioFrame() | 返回一個流式合成片段的增量二進制音頻數據,可能為空。 |
getTimestamp | Sentence getTimestamp() | 返回當前流式合成的句子所對應的句級別時間戳。 |
通過Flowable的流式調用
Java SDK還額外提供了通過Flowable流式調用的方式進行語音合成。在Flowable對象onComplete()后,可以通過Synthesis對象的getTimestamps()和getAudioData()獲取完整結果。
以下示例展示了通過Flowable對象的blockingForEach接口,阻塞式的獲取每次流式返回的SpeechSynthesisResult類型數據msg。
調用示例
package com.alibaba.dashscope.sample;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.tts.SpeechSynthesizer;
import io.reactivex.Flowable;
public class Main {
public static void main(String[] args) {
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
SpeechSynthesisParam param = SpeechSynthesisParam.builder()
.model("sambert-zhichu-v1")
.text("今天天氣怎么樣")
.sampleRate(48000)
.enableWordTimestamp(true)
.apiKey("your-dashscope-api-key")
.build();
Flowable<SpeechSynthesisResult> flowable = synthesizer.streamCall(param);
flowable.blockingForEach(
msg -> {
if (msg.getAudioFrame() != null) {
// do something with the audio frame
System.out.println("getAudioFrame");
}
if (msg.getTimestamp() != null) {
// do something with the timestamp
System.out.println("getTimestamp");
}
}
);
System.exit(0);
}
}
返回結果說明
該接口主要通過返回的Flowable<SpeechSynthesisResult>來獲取流式結果,也可以在Flowable的所有流式數據返回完成后通過對應SpeechSynthesizer對象的getAudioData和getTimestamps來獲取完整的合成結果和完整的時間戳。關于Flowable的使用,請參見rxjava API。
狀態碼說明
DashScope通用狀態碼,請查閱:返回狀態碼說明。