package com.artfess.rescue.utils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class StrConverVoiceUtils { /** * 字符串文本转 wav格式 语音文件 * @param text 要读的文字字符串 */ public static String generateSpeechFile(String text) { String os = System.getProperty("os.name").toLowerCase(); String fileName = "alert_" + System.currentTimeMillis() + (os.contains("win") ? ".wav" : ".mp3"); Path outputPath = Paths.get(System.getProperty("java.io.tmpdir"), "voice_files", fileName); try { Files.createDirectories(outputPath.getParent()); if (os.contains("win")) { // Windows: 调用 PowerShell SAPI String command = String.format( "PowerShell -Command \"Add-Type -AssemblyName System.Speech; " + "$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer; " + "$speak.SetOutputToWaveFile('%s'); " + "$speak.Speak('%s'); $speak.Dispose();\"", outputPath.toString().replace("\\", "\\\\"), text.replace("'", "''") ); Runtime.getRuntime().exec(command).waitFor(); } else { // Linux: 调用 espeak + ffmpeg Path tempWav = outputPath.resolveSibling("temp.wav"); ProcessBuilder espeakPb = new ProcessBuilder("espeak", "-v", "zh", "-w", tempWav.toString(), text); ProcessBuilder ffmpegPb = new ProcessBuilder("ffmpeg", "-i", tempWav.toString(), "-codec:a", "libmp3lame", outputPath.toString()); espeakPb.start().waitFor(); ffmpegPb.start().waitFor(); Files.deleteIfExists(tempWav); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } // return "/voices/"+fileName; return "/voices/alert_1752806982355.wav"; } }