http实时语音

2022-04-30  本文已影响0人  凌康ACG

上次我编写了用websocket传输视频 https://www.jianshu.com/p/a9ee255fc0ae ,发现有很多人问怎么没有语音。

还有就是之前觉得简书广告多就离开了,转战CSDN(床上等你)。快来关注给我点个赞吧:
https://blog.csdn.net/weixin_44480167

语音的本质还是字节的传输,声音采集→转化字节→传输→播放。按照这个思路,我们可以开发一个即时通话的系统,下面我会演示基于http的实时语音。

要知道,现在的音视频入门削微有点难度。网上的那些SDK都是收费教你做人的,你看到这篇文章就等于白嫖

只要你逻辑处理得好就能做到超低延迟,性能就别在意了,现在的设备分分钟可以忽略这点能耗,大规模就需要花点信息,例如使用FFmpeg做混音、消除回响处理(多人通话)

创建普通springboot项目

我们随手创建一个springboot项目

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

编写一个controller

package top.lingkang.avdemo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import javax.sound.sampled.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

/**
 * @author lingkang
 * Created by 2022/4/30
 */
@RestController
public class WebController {
    @GetMapping("")
    public ModelAndView index() {
        return new ModelAndView("index");
    }

    // 用于实时响应音频
    @GetMapping("/a")
    public void a(HttpServletResponse response) throws Exception {
        System.out.println("进入音频录制....");
        response.setContentType("audio/wav");// 要在http响应内容为wav,用于浏览器识别和播放

        // 基本声道设置、声音采集等
        AudioFormat format = new AudioFormat(16000, 8, 2, true, true);
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
        TargetDataLine auline = (TargetDataLine) AudioSystem.getLine(info);
        auline.open(format);
        auline.start();

        // 创建一个临时文件用来一边读取一边写入音频   实际开发应该注意内存溢出等问题处理
        File temp = File.createTempFile(".wav", ".tmp");
        new Thread(new Runnable() {// 用线程来读取
            @Override
            public void run() {
                try {
                    Thread.sleep(100);
                    byte[] by = new byte[512];
                    InputStream in = new FileInputStream(temp);
                    for (; ; ) {
                        int read = in.read(by);
                        if (read == -1) {// 未能读到字节就延迟一下
                            Thread.sleep(500);
                        } else {
                            response.getOutputStream().write(by);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

        AudioInputStream ais = new AudioInputStream(auline);
        // 写入 wav  一定要格式转化,否则浏览器无法识别流
        AudioSystem.write(ais, AudioFileFormat.Type.WAVE, temp);
    }
}

以上使用java的音源录入其实挺拉胯的

然后编写一个前端html用于实时播放

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<audio src="./a" controls="controls">wav</audio>
</body>
</html>

点击播放
访问


image.png

即可达到实时语音通话。

想要听到效果,电脑端用网易云播放音乐,再使用手机打开 192.168.31.199:8080 (与电脑处于局域网下,同一个路由器即可) 走远点,别让回声影响。

例如自己用js处理自动播放、使用多线程、netty等实现字节流分发。要求高性能还能用go、rust、c++等实现音频流转发。
其他文章:websocket实现简单的直播:https://www.jianshu.com/p/a9ee255fc0ae

点个赞再走呗

上一篇下一篇

猜你喜欢

热点阅读