上次我编写了用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>
点击播放
访问
即可达到实时语音通话。
想要听到效果,电脑端用网易云播放音乐,再使用手机打开 192.168.31.199:8080 (与电脑处于局域网下,同一个路由器即可) 走远点,别让回声影响。
例如自己用js处理自动播放、使用多线程、netty等实现字节流分发。要求高性能还能用go、rust、c++等实现音频流转发。
其他文章:websocket实现简单的直播:https://www.jianshu.com/p/a9ee255fc0ae