基于Java JLayer的可暂停播放器无法播放音频求助
基于JLayer实现可暂停播放器无法播放的问题排查
我尝试基于JLayer包的Advanced Player实现一个可暂停的播放器对象,参考了Stack Overflow上的实现方案,但目前无法播放音频。以下是我的PausablePlayer类代码及实例化方式,恳请帮忙排查问题原因:
PausablePlayer类代码
package com.musicstreamingapp; import java.io.ByteArrayInputStream; import java.io.InputStream; import javazoom.jl.player.advanced.AdvancedPlayer; import javazoom.jl.decoder.JavaLayerException; import javazoom.jl.player.AudioDevice; public class PausablePlayer { private final static int NOTSTARTED = 0; private final static int PLAYING = 1; private final static int PAUSED = 2; private final static int FINISHED = 3; // 实际处理播放的核心对象 private final AdvancedPlayer player; // 用于线程通信的锁对象 private final Object playerLock = new Object(); // 播放器状态标记 private int playerStatus = NOTSTARTED; public PausablePlayer(final InputStream inputStream) throws JavaLayerException { this.player = new AdvancedPlayer(inputStream); } public PausablePlayer(final InputStream inputStream, AudioDevice audioDevice) throws JavaLayerException { this.player = new AdvancedPlayer(inputStream, audioDevice); } /** * 启动播放(暂停时恢复) */ public void play() throws JavaLayerException { synchronized (playerLock) { switch (playerStatus) { case NOTSTARTED: final Runnable r = new Runnable() { public void run() { playInternal(); } }; final Thread t = new Thread(r); // 移除了原代码中的守护线程设置 t.setPriority(Thread.MAX_PRIORITY); playerStatus = PLAYING; t.start(); break; case PAUSED: resume(); break; default: break; } } } /** * 暂停播放,返回是否成功进入暂停状态 */ public boolean pause() { synchronized (playerLock) { if (playerStatus == PLAYING) { playerStatus = PAUSED; } return playerStatus == PAUSED; } } /** * 恢复播放,返回是否成功进入播放状态 */ public boolean resume() { synchronized (playerLock) { if (playerStatus == PAUSED) { playerStatus = PLAYING; playerLock.notifyAll(); } return playerStatus == PLAYING; } } /** * 停止播放,未播放时无操作 */ public void stop() { synchronized (playerLock) { playerStatus = FINISHED; playerLock.notifyAll(); } } private void playInternal() { while (playerStatus != FINISHED) { try { // 每次播放一帧音频 boolean ret = player.play(1); if (!ret) { break; } } catch (final JavaLayerException e) { e.printStackTrace(); // 添加异常打印,排查解码错误 break; } // 检查是否暂停或终止 synchronized (playerLock) { while (playerStatus == PAUSED) { try { playerLock.wait(); } catch (final InterruptedException e) { // 中断时终止播放器 break; } } } } close(); } /** * 关闭播放器,无论当前状态如何 */ public void close() { synchronized (playerLock) { playerStatus = FINISHED; } try { player.close(); } catch (final Exception e) { // 忽略关闭时的异常 } } // 原代码末尾多余的{}代码块已删除 }
播放器实例化代码
public static void playAudio(byte[] song) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(song); try { PausablePlayer player = new PausablePlayer(byteArrayInputStream); player.play(); // 暂停恢复测试 Thread.sleep(5000); // 播放5秒后暂停 player.pause(); System.out.println("已暂停歌曲"); Thread.sleep(5000); // 暂停5秒后恢复 player.resume(); System.out.println("已恢复歌曲"); // 播放5秒后停止 Thread.sleep(5000); player.stop(); } catch (JavaLayerException | InterruptedException e) { e.printStackTrace(); System.out.println("播放音频出错: " + e.getMessage()); } }
问题排查与修复建议
- 修正语法错误:原
PausablePlayer类末尾存在多余的{ }代码块,会导致编译失败,必须删除。 - 验证音频数据完整性:确保传入的
byte[] song是完整且有效的MP3文件字节数据,可以先尝试用普通AdvancedPlayer直接播放该字节数组,确认音频本身无损坏。 - 添加异常日志:在
playInternal的JavaLayerException捕获块中添加打印语句,排查是否是解码过程中出现错误。 - 调整线程测试逻辑:如果音频时长较短,主线程的
Thread.sleep会导致播放器在睡眠期间已经播放完毕,后续暂停/恢复操作无效。可以添加状态检查,或更换更长的测试音频。 - 显式初始化音频设备:如果默认音频设备初始化失败,可尝试显式创建音频设备并传入播放器构造函数:
AudioDevice audioDevice = new JavaSoundAudioDevice(); audioDevice.open(player.getDecoder()); PausablePlayer player = new PausablePlayer(byteArrayInputStream, audioDevice);
内容的提问来源于stack exchange,提问作者Bennett Godinho-Nelson
相关产品推荐
相关产品推荐

