简单集成百度智能云语音合成技术之短文本语音在线合成

废话不多说,咋们先注册好百度智能云账号,创建好语音合成的应用

1.配置依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.application.properties文件\application.yml文件配置

baidu.tts.api-key=应用的API Key
baidu.tts.secret-key=应用的 Secret Key

3.服务层

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;

@Service
public class BaiduTtsService {
    @Value("${baidu.tts.api-key}")
    private String apiKey;

    @Value("${baidu.tts.secret-key}")
    private String secretKey;

    private final RestTemplate restTemplate = new RestTemplate();

    // 获取Access Token(有效期30天)
    private String getAccessToken() {
        String authUrl = "https://aip.baidubce.com/oauth/2.0/token" +
                "?grant_type=client_credentials" +
                "&client_id=" + apiKey +
                "&client_secret=" + secretKey;

        ResponseEntity<Map> response = restTemplate.getForEntity(authUrl, Map.class);
        return (String) response.getBody().get("access_token");
    }

    // 调用语音合成API
    public byte[] textToSpeech(String encodedText, String voiceType, String pitch) {
        try {
            // 解码前端传递的URL编码文本
            String decodedText = URLDecoder.decode(encodedText, "UTF-8");

            String accessToken = getAccessToken();
            String ttsUrl = "https://tsn.baidu.com/text2audio" +
                    "?tex=" + encodeText(decodedText) + // 重新编码给百度API
                    "&lan=zh" +
                    "&cuid=123" +
                    "&ctp=1" +
                    "&tok=" + accessToken +
                    "&per=" + voiceType + // 音色
                    "&pit=" + pitch; // 音调
            return restTemplate.getForObject(ttsUrl, byte[].class);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("解码失败", e);
        }
    }
    
    // 处理中文编码
    private String encodeText(String text) {
        try {
            return URLEncoder.encode(text, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("文本编码失败", e);
        }
    }
}

(该案例用的短文本在线合成+基础音库) 

4.Controller层

import com.lxy.other.service.BaiduTtsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TttsController {

    @Autowired
    private BaiduTtsService ttsService;

    @GetMapping("/generate-audio")
    public ResponseEntity<ByteArrayResource> generateAudio(
            @RequestParam String text,
            @RequestParam(defaultValue = "0") String voiceType, // 默认音色
            @RequestParam(defaultValue = "5") String pitch // 默认音调
    ) {
        byte[] audioData = ttsService.textToSpeech(text, voiceType, pitch);

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType("audio/mp3"))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"audio.mp3\"")
                .body(new ByteArrayResource(audioData));
    }
}

前端代码我也一块提供测试:

样式:

 <style>
        .container {
            max-width: 800px;
            margin: 20px auto;
            padding: 20px;
            font-family: "Microsoft YaHei";
        }
        .control-panel {
            margin: 20px 0;
            padding: 15px;
            border: 1px solid #e4e7ed;
            border-radius: 8px;
        }
        .slider-container {
            display: flex;
            align-items: center;
            margin: 15px 0;
        }
        .voice-type {
            margin-top: 15px;
            padding: 10px;
            border-top: 1px solid #ebeef5;
        }
        audio {
            width: 30%;
            margin: 15px 0;
        }
        button {
            background: #409eff;
            color: white;
            border: none;
            padding: 10px 25px;
            border-radius: 4px;
            cursor: pointer;
        }
        button:disabled {
            background: #a0cfff;
            cursor: not-allowed;
        }
    </style>
<div id="app" class="container">
    <audio :src="audioUrl" controls id="player"></audio>
    <input type="text" v-model="inputText" placeholder="输入要朗读的内容">
    <div class="voice-type">
        <label>选择音色:</label>
        <el-select v-model="voiceType" placeholder="请选择音色">
            <el-option label="标准女声" value="0"></el-option>
            <el-option label="标准男声" value="1"></el-option>
            <el-option label="情感男声" value="3"></el-option>
            <el-option label="情感女声" value="5"></el-option>
        </el-select>
    </div>
    <div class="slider-container">
        <label>音调:</label>
        <el-slider v-model="pitch" :min="0" :max="15" show-input></el-slider>
    </div>

    <button
            @click="playAudio"
            :disabled="isLoading">  <!-- 防止重复点击 -->

    {{ isLoading ? '生成中...' : '播放' }}
    </button>
    <p v-if="errorMessage" style="color: red;">{{ errorMessage }}</p>
</div>
<script>
    var vue = new Vue({
        el: "#app",
        data: {
            inputText: "",     // 绑定输入框内容
            audioUrl: "",      // 存储音频URL
            errorMessage: "",   // 错误信息
            audioElement: null,  // 新增音频元素引用
            isLoading:false,
            voiceType: "0",    // 默认音色
            pitch: 5           // 默认音调
        },
        mounted() {
            // 初始化时获取音频元素引用
            this.audioElement = document.getElementById("player");
            // 添加音频加载完成监听
            this.audioElement.addEventListener('canplaythrough', () => {
                this.audioElement.play().catch(error => {
                    console.log('自动播放被阻止:', error);
                });
            });
        },
        methods: {
            async playAudio() {
                try {
                    this.isLoading = true;
                    this.errorMessage = "";
                    this.audioUrl = ""; // 清空旧地址

                    // 验证输入
                    if (!this.inputText.trim()) {
                        this.errorMessage = "请输入要朗读的内容";
                        return;
                    }

                    // 暂停当前播放并重置
                    this.audioElement.pause();
                    this.audioElement.currentTime = 0;

                    // 编码并发送请求
                    const encodedText = encodeURIComponent(this.inputText);
                    const response = await fetch(`/generate-audio?text=${encodedText}&voiceType=${this.voiceType}&pitch=${this.pitch}`);

                    if (!response.ok) throw new Error('网络响应异常');
                    const blob = await response.blob();

                    // 生成新地址(需先释放旧地址)
                    if(this.audioUrl) URL.revokeObjectURL(this.audioUrl);
                    this.audioUrl = URL.createObjectURL(blob);

                } catch (error) {
                    console.error('播放失败:', error);
                    this.errorMessage = "音频播放失败:" + error.message;
                } finally {
                    this.isLoading = false;
                }
            }
        }
    });
</script>

对于更多音色的探索可查看百度智能云AI开放平台

地址:语音技术https://ai.baidu.com/ai-doc/SPEECH/Rluv3uq3d

对于长文本在线语音合成技术可移步另一篇文章:简单集成百度智能云语音合成技术之长文本语音在线合成-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值