微软云语音识别ASR示例Demo

对象存储服务 OSS 对应 Azure Blob Storage

语音识别 ASR 对应 Azure Speech-to-Text

语音合成 TTS 对应 Azure Text-to-Speech

上传..mp3文件或者上传OSS地址 返回音频的文字示例demo

依赖

复制代码
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--   microsoft ASR     -->
        <dependency>
            <groupId>com.microsoft.cognitiveservices.speech</groupId>
            <artifactId>client-sdk</artifactId>
            <version>1.43.0</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

代码 在application.properties或者yaml中配置key和endpoint

复制代码
package com.example.microsoftasr.controller;

import com.microsoft.cognitiveservices.speech.*;
import com.microsoft.cognitiveservices.speech.audio.AudioConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.net.URI;
import java.nio.file.Files;

@RestController
@RequestMapping("/asr")
public class TestController {

    @Value("${azure.speech.key}")
    private String speechKey;

    @Value("${azure.speech.endpoint}")
    private String speechEndpoint;

    @GetMapping("/hello")
    public String test() {
        return "Hello World";
    }

    @PostMapping("/recognize")
    public String recognize(@RequestParam(value = "file", required = false) MultipartFile file,
                            @RequestParam(value = "url", required = false) String ossUrl) {
        if ((file == null || file.isEmpty()) && (ossUrl == null || ossUrl.isBlank())) {
            return "未提供音频文件或音频地址";
        }

        File tempInput = null;
        File tempWav = null;

        try {
            // 1. 保存临时原始音频
            if (file != null && !file.isEmpty()) {
                String suffix = getSuffix(file.getOriginalFilename());
                tempInput = File.createTempFile("audio-input-", "." + suffix);
                file.transferTo(tempInput);
            } else {
                String suffix = getSuffix(ossUrl);
                tempInput = File.createTempFile("audio-input-", "." + suffix);
                try (var in = new java.net.URL(ossUrl).openStream()) {
                    Files.copy(in, tempInput.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
                }
            }

            // 2. 转换成 WAV(16kHz 单声道)
            tempWav = File.createTempFile("audio-output-", ".wav");
            if (!getSuffix(tempInput.getName()).equalsIgnoreCase("wav")) {
                ProcessBuilder pb = new ProcessBuilder(
                        "F:\\ffmpeg-7.1.1-full_build\\ffmpeg-7.1.1-full_build\\bin\\ffmpeg.exe", "-y",
                        "-i", tempInput.getAbsolutePath(),
                        "-ar", "16000",
                        "-ac", "1",
                        tempWav.getAbsolutePath()
                );
                Process process = pb.inheritIO().start();
                int exitCode = process.waitFor();
                if (exitCode != 0) return "ffmpeg 转换失败,exitCode=" + exitCode;
            } else {
                Files.copy(tempInput.toPath(), tempWav.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
            }

            // 3. 调用微软 ASR 识别
            SpeechConfig speechConfig = SpeechConfig.fromEndpoint(new URI(speechEndpoint), speechKey);
            speechConfig.setSpeechRecognitionLanguage("zh-CN");

            try (AudioConfig audioConfig = AudioConfig.fromWavFileInput(tempWav.getAbsolutePath());
                 SpeechRecognizer recognizer = new SpeechRecognizer(speechConfig, audioConfig)) {
                SpeechRecognitionResult result = recognizer.recognizeOnceAsync().get();
                if (result.getReason() == ResultReason.RecognizedSpeech) {
                    return result.getText();
                } else {
                    return "识别失败: " + result.getReason();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            return "识别异常: " + e.getMessage();
        } finally {
            try {
                if (tempInput != null) Files.deleteIfExists(tempInput.toPath());
                if (tempWav != null) Files.deleteIfExists(tempWav.toPath());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    private String getSuffix(String filenameOrUrl) {
        if (filenameOrUrl == null || !filenameOrUrl.contains(".")) return "tmp";
        return filenameOrUrl.substring(filenameOrUrl.lastIndexOf('.') + 1);
    }

}
相关推荐
黎燃6 小时前
短视频平台内容推荐算法优化:从协同过滤到多模态深度学习
人工智能
飞哥数智坊7 小时前
多次尝试用 CodeBuddy 做小程序,最终我放弃了
人工智能·ai编程
后端小肥肠7 小时前
别再眼馋 10w + 治愈漫画!Coze 工作流 3 分钟出成品,小白可学
人工智能·aigc·coze
唐某人丶10 小时前
教你如何用 JS 实现 Agent 系统(2)—— 开发 ReAct 版本的“深度搜索”
前端·人工智能·aigc
FIT2CLOUD飞致云11 小时前
九月月报丨MaxKB在不同规模医疗机构的应用进展汇报
人工智能·开源
阿里云大数据AI技术11 小时前
【新模型速递】PAI-Model Gallery云上一键部署Qwen3-Next系列模型
人工智能
袁庭新11 小时前
全球首位AI机器人部长,背负反腐重任
人工智能·aigc
机器之心11 小时前
谁说Scaling Law到头了?新研究:每一步的微小提升会带来指数级增长
人工智能·openai
算家计算11 小时前
AI配音革命!B站最新开源IndexTTS2本地部署教程:精准对口型,情感随心换
人工智能·开源·aigc
量子位12 小时前
马斯克周末血裁xAI 500人
人工智能·ai编程