我需要使用MediaPlayer
Youtube 同步音频文件和流式传输音频,使用YoutubePlayer
.
我在启动时遇到了错误MediaPlayer
。它在一些延迟后开始,并且音轨不同步。使用SoundPool
不好,因为音频文件很重。
是否可以管理 MediaPlayer 的启动,或预缓冲音频(将音频解码为 PCM 并播放?)?
提前致谢。
我需要使用MediaPlayer
Youtube 同步音频文件和流式传输音频,使用YoutubePlayer
.
我在启动时遇到了错误MediaPlayer
。它在一些延迟后开始,并且音轨不同步。使用SoundPool
不好,因为音频文件很重。
是否可以管理 MediaPlayer 的启动,或预缓冲音频(将音频解码为 PCM 并播放?)?
提前致谢。
我不熟悉 YoutubePlayer,但就启动音频文件时减少延迟而言,使用 AudioTrack 可能会更好(或者如果您对 openSL 感到满意——请查看此视频)。
我用来同步音频并获得不错结果的一个简单修复方法是设置一个 AudioTrack 并将音频文件中的 PCM 数据读取到一个字节数组中。然后创建一个带有 AudioTrack 播放的线程并在里面写命令。当您准备好开始播放音频文件时,只需在线程上调用 start。显然,采样率、通道和格式取决于您正在流式传输的音频文件。
int minBufferSize = AudioTrack.getMinBufferSize(441000, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
at = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
filepath = Environment.getExternalStorageDirectory().getPath() + File.separator + "audiofile.wav";
fp = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "audiofile.wav");
count = 0;
data = new byte[(int) fp.length()];
try {
fis = new FileInputStream(filepath);
dis = new DataInputStream(fis);
while((count = dis.read(data, 0, (int) fp.length())) > -1){}
data = null;
dis.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
atThread = new Thread(new Runnable() {
public void run() {
at.play();
at.write(data, 0, (int) fp.length());
data = null; at.stop(); at.flush(); at.release();
}
});
希望这可以帮助!
编辑:
非常感谢@WilliamMorrison 的帮助!在此处修改@inazaruk 的答案后,我能够播放单独的波形文件,而无需将它们的整个文件写入内存。呸!
AudioTrack song_1, song_2;
boolean stop = false;
Button start_btn, stop_btn;
DataInputStream dis_1, dis_2;
File file_1 = new File(Environment.getExternalStorageDirectory().toString() + "/song_1.wav");
File file_2 = new File(Environment.getExternalStorageDirectory().toString() + "/song_2.wav");
FileInputStream fis_1, fis_2;
int minBufferSize;
Thread thread_1, thread_2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start_btn = (Button)findViewById(R.id.start);
start_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
start();
}
});
stop_btn = (Button)findViewById(R.id.stop);
stop_btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stop();
}
});
}
Runnable read_song1 = new Runnable() {
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
byte [] audio_data = new byte[minBufferSize];
try {
while(!stop) {
dis_1.read(audio_data, 0, minBufferSize);
song_1.write(audio_data, 0, audio_data.length);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
Runnable read_song2 = new Runnable()
{
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
byte [] audio_data = new byte[minBufferSize];
try {
while(!stop) {
dis_2.read(audio_data, 0, minBufferSize);
song_2.write(audio_data, 0, audio_data.length);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
};
void start() {
try {
fis_1 = new FileInputStream(file_1); fis_2 = new FileInputStream(file_2);
dis_1 = new DataInputStream(fis_1); dis_2 = new DataInputStream(fis_2);
stop = false;
minBufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
song_1 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
song_2 = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, AudioTrack.MODE_STREAM);
song_1.play(); song_2.play();
thread_1 = new Thread(read_song1); thread_2 = new Thread(read_song2);
thread_1.start(); thread_2.start();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
void stop() {
stop = true;
song_1.stop(); song_2.stop();
song_1.flush(); song_2.flush();
song_1.release(); song_2.release();
try {
dis_1.close(); dis_2.close();
fis_1.close(); fis_2.close();
}
catch (IOException e) {
e.printStackTrace();
}
}