简介:本文详细介绍了如何使用Java实现文字转语音功能并生成语音文件,包括FreeTTS和Java Speech API两种方案的对比与实现,适合开发者快速掌握核心技能。
文字转语音(Text-to-Speech, TTS)技术作为人机交互的重要环节,广泛应用于智能客服、无障碍辅助、有声读物等领域。Java凭借其跨平台特性和丰富的生态库,成为实现TTS功能的理想选择。本文将通过两种主流方案(FreeTTS库和Java Speech API),结合代码示例,系统讲解如何实现文字转语音并生成WAV/MP3文件,同时分析技术选型、性能优化及常见问题解决方案。
FreeTTS是一个开源的Java TTS引擎,基于CMU的Flite项目开发,支持中英文混合转换,无需依赖外部服务。其核心优势在于:
适用场景:内网环境、需要完全控制语音生成流程的项目。
Java Speech API是JSR-113规范定义的接口,需配合第三方语音引擎(如Microsoft Speech API或Mac OS X语音引擎)使用。其特点包括:
javax.speech包提供统一API适用场景:需要高质量语音输出且可接受外部依赖的项目。
<!-- Maven配置 --><dependency><groupId>com.sun.speech.freetts</groupId><artifactId>freetts</artifactId><version>1.2.2</version></dependency>
import com.sun.speech.freetts.Voice;import com.sun.speech.freetts.VoiceManager;public class FreeTTSDemo {public static void main(String[] args) {// 初始化语音管理器VoiceManager voiceManager = VoiceManager.getInstance();// 获取kevin16语音(英文男声)Voice voice = voiceManager.getVoice("kevin16");if (voice != null) {voice.allocate();// 合成语音并输出到控制台voice.speak("Hello, this is a text to speech demo.");voice.deallocate();} else {System.err.println("Cannot find a voice named kevin16");}}}
通过AudioPlayer和AudioOutputStream实现文件输出:
import com.sun.speech.freetts.Voice;import com.sun.speech.freetts.VoiceManager;import com.sun.speech.freetts.audio.AudioPlayer;import com.sun.speech.freetts.audio.SingleFileAudioPlayer;import java.io.File;import java.io.IOException;public class FreeTTSFileDemo {public static void main(String[] args) {VoiceManager vm = VoiceManager.getInstance();Voice voice = vm.getVoice("kevin16");if (voice != null) {try {// 创建WAV文件输出流AudioPlayer player = new SingleFileAudioPlayer("output.wav",SingleFileAudioPlayer.DEFAULT_FORMAT,22050, // 采样率16 // 位深);voice.setAudioPlayer(player);voice.allocate();String text = "This text will be saved to a WAV file.";voice.speak(text);voice.deallocate();player.close();System.out.println("Audio file generated successfully.");} catch (IOException e) {e.printStackTrace();}}}}
FreeTTS默认不支持中文,需通过以下方式扩展:
cmulex词典包(需单独下载)com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory)
-Djavax.speech.resource.path=/path/to/speech.properties
import javax.speech.*;import javax.speech.synthesis.*;import java.util.Locale;public class JSAPIDemo {public static void main(String[] args) {try {// 初始化语音合成器SynthesizerModeDesc desc = new SynthesizerModeDesc(Locale.US,"general",Voice.GENDER_DONT_CARE,Voice.AGE_DONT_CARE,null);Synthesizer synthesizer = Central.createSynthesizer(desc);synthesizer.allocate();synthesizer.resume();// 设置语音属性synthesizer.getSynthesizerProperties().setVoice(new Voice("kevin16",Voice.GENDER_MALE,Voice.AGE_MIDDLE_ADULT,null));// 合成语音synthesizer.speakPlainText("Hello from Java Speech API", null);synthesizer.waitEngineState(Synthesizer.QUEUE_EMPTY);synthesizer.deallocate();} catch (Exception e) {e.printStackTrace();}}}
需通过AudioSystem捕获音频流:
import javax.sound.sampled.*;import java.io.*;public class JSAPIFileWriter {public static void saveAudio(byte[] audioData, File file) throws IOException {try (ByteArrayInputStream bais = new ByteArrayInputStream(audioData);AudioInputStream ais = new AudioInputStream(bais,new AudioFormat(22050, 16, 1, true, false),audioData.length / 2); // 估算帧数FileOutputStream fos = new FileOutputStream(file)) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = ais.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);}}}}
deallocate()释放语音资源Voice对象避免重复初始化
import java.util.concurrent.*;public class AsyncTTS {private final ExecutorService executor = Executors.newFixedThreadPool(2);public void speakAsync(String text) {executor.submit(() -> {Voice voice = VoiceManager.getInstance().getVoice("kevin16");if (voice != null) {voice.allocate();voice.speak(text);voice.deallocate();}});}}
Cannot find a voice named kevin16
解决方案:
freetts.jar是否包含语音数据
System.setProperty("freetts.voices", "/path/to/voices");
原因:FreeTTS默认不支持GBK编码
解决方案:
String text = new String("中文".getBytes("UTF-8"), "UTF-8");
检查点:
本文通过FreeTTS和Java Speech API两种方案,系统展示了Java实现文字转语音并生成音频文件的全流程。FreeTTS方案适合内网轻量级应用,而Java Speech API更适合需要高质量语音输出的场景。未来,随着深度学习技术的发展,基于神经网络的TTS引擎(如Tacotron、FastSpeech)将逐步成为主流,开发者可关注相关Java封装库的演进。
推荐学习资源: