微软云语音识别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);
    }

}
相关推荐
AI编程教父35 分钟前
企业AI转型做自动化,哪些靠规则、哪些交给AI?红烁AI企业AI培训用两类任务对比
人工智能
m0_7196408735 分钟前
适合教学科研的人工智能实验室建设方案有哪些?(含测评)
人工智能·经验分享
智学AI36 分钟前
AI博主写作素材管理方法分享:资料归集、笔记关联与文档归档
人工智能·笔记
dozenyaoyida36 分钟前
AI与大模型新闻日报 | 2026-10-30
人工智能·ai·chatgpt·大模型·新闻
Rocky Ding*41 分钟前
深入浅出Xiaomi-Lens-0技术解析:像素监督如何改变视觉推理
论文阅读·人工智能·深度学习·机器学习·aigc·多模态·ai-native
万岳软件开发小城1 小时前
AI数字人系统源码如何实现批量视频生成?任务队列与自动化生产流程解析
人工智能·自动化·语音识别·ai数字人小程序·ai数字人系统源码·ai数字人软件开发·ai数字人平台开发
默|笙1 小时前
【AI应用】认识机器学习与深度学习
人工智能·深度学习·机器学习
TangGeeA1 小时前
数据库、SQL 与 DB AI
数据库·人工智能·sql
火山引擎开发者社区1 小时前
案例实践 | 让检索为 Agent 而生:ContextSearch 重构企业售前知识库
人工智能
青蓝智慧马老师1 小时前
大模型应用落地,到底靠什么?RAG、智能体和上下文工程一次讲清
人工智能