wangshuo'blog

wangshuo'blog

http | java 直接播放 http 响应流的内容

http | java 直接播放 http 响应流的内容

2023-05-08 14:26:48

引言

之前帮其他人写一个简单的 java 本地词典程序,其中包括一个阅读功能,选中单词,阅读单词。开始的想法是直接调用 Baidu Fanyi 的接口。

最简单、容易理解的实现发送请求下载 mp3 文件到本地,播放本地的 mp3 文件。更好的方式是直接转换流,就省去的下载的这个过程

1
2
发送请求 - 下载mp3文件到本地 - 播放 mp3
发送请求 - 读取响应流并播放

其实,这个功能有点偏题了,因为播放必须要联网,和本地这个有冲突。因为想要看看如何实现,就把这个功能添加上去了

java 发送 http 请求,直接播放响应

http 请求使用了 JDK 原声的 Http Client 相关的类,播放 mp3 文件使用到了一个第三方库 jlayerMaven地址

代码

依赖

1
2
3
4
5
<dependency>
<groupId>javazoom</groupId>
<artifactId>jlayer</artifactId>
<version>1.0.1</version>
</dependency>

HTTPPlayer类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import javazoom.jl.player.Player;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HTTPPlayer {
private Player player;
private HttpURLConnection connection;

public void play(String urlString) throws Exception {
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
// 添加请求头
connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
connection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
connection.setRequestProperty("Accept-Charset", "utf-8");
connection.setRequestProperty("Connection", "keep-alive");
connection.setRequestProperty("Cache-Control", "max-age=0");
connection.setRequestProperty("Accept-Encoding", "gzip, deflate, br");

connection.connect();

InputStream inputStream = new BufferedInputStream(connection.getInputStream());
player = new Player(inputStream);
player.play();
}

public void stop() {
if (player != null) {
player.close();
}
if (connection != null) {
connection.disconnect();
}
}
}

测试

1
2
HTTPPlayer player = new HTTPPlayer();
player.play("http://example.com/audio.mp3");

简单封装一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void playSound(String word, String language) {
String urlString = "";
switch (language) {
case "Chinese":
urlString = "https://fanyi.baidu.com/gettts?lan=zh&text=" + word + "&spd=5&source=web";
break;
case "English":
urlString = "https://fanyi.baidu.com/gettts?lan=en&text=" + word + "&spd=3&source=web";
break;
default:
throw new IllegalArgumentException("Unsupported language: ");
}
try {
HTTPPlayer httpPlayer = new HTTPPlayer();
httpPlayer.play();
} catch (Exception e) {
e.printStackTrace();
try {
Thread.sleep(3*1000);
playSound(word, language);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}

在实际的使用过程中,偶尔会出现服务错误相关的状态码,不清楚是否是 baidu 检测到了是脚本发送的。

做了一个简单的解决方案,如果发送错误,就递归调用一下。

优点

和 “发送请求保存文件到本地,在进行播放” 相比的优点

  1. 资源利用效率:该代码通过使用缓冲输入流(BufferedInputStream),直接将HTTP响应的输入流与播放器关联,实现了边接收数据边播放的功能。相比先将文件保存到本地再进行播放,避免了在磁盘上进行中间存储的开销,节省了存储空间和I/O操作。
  2. 响应速度:由于不需要等待整个文件下载完成后再进行播放,而是边下载边播放,可以更快地开始播放音频。这对于实时性要求较高的应用场景,如在线音乐或音频直播等,能够提供更好的用户体验。
  3. 简洁性和便利性:代码将请求、下载和播放的逻辑整合在一起,使得使用者可以更方便地使用HTTPPlayer类进行音频播放。相比手动发送请求保存文件到本地,再进行播放的方式,代码更加简洁、易于理解和维护。

参考