我正在尝试制作录制音频的示例,数据存储由应用处理,而不是MediaRecorder
。用例包括将记录存储在内部存储器或加密记录。
原则上,这应该使用createPipe()
上ParcelFileDescriptor
创建的管道,但输出格式不正确。
首先,here is a sample project使用MediaRecorder
“自然地”记录,MediaRecorder
直接写入外部存储上的输出文件。这个应用程序工作正常,输出可以由记录它的Android设备或我的Linux盒子上的VLC播放。
Here is my createPipe()
variation of this project。从一般MediaRecorder
配置(例如setOutputFormat()
)的角度来看,它与第一个配置相同,因此代码可能是正确的。
但是,我通过以下方式提供输出:
recorder.setOutputFile(getStreamFd());
getStreamFd()
使用createPipe()
的位置,生成后台线程以从管道中读取,并返回写入结束以供MediaRecorder
使用:
private FileDescriptor getStreamFd() {
ParcelFileDescriptor[] pipe=null;
try {
pipe=ParcelFileDescriptor.createPipe();
new TransferThread(new AutoCloseInputStream(pipe[0]),
new FileOutputStream(getOutputFile())).start();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
}
return(pipe[1].getFileDescriptor());
}
TransferThread
是一个经典的java.io
流到流的复制例程,增加了智能来刷新和同步输出文件:
static class TransferThread extends Thread {
InputStream in;
FileOutputStream out;
TransferThread(InputStream in, FileOutputStream out) {
this.in=in;
this.out=out;
}
@Override
public void run() {
byte[] buf=new byte[8192];
int len;
try {
while ((len=in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.flush();
out.getFD().sync();
out.close();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception transferring file", e);
}
}
}
当我运行第二个应用程序时,我得到一个输出文件,通过十六进制编辑器的粗略检查,似乎基本上没问题。 IOW,它不像是一个零字节文件,或者充满了无法识别的乱码。它充满了与第一个应用程序的输出类似的乱码。但是,Android和VLC都无法播放它。
如果我不得不猜测,我会认为我在从管道读取时搞砸了一些东西,但我不确定我哪里出错了。
有什么建议吗?
提前致谢!
答案 0 :(得分:13)
我猜这与我对你的其他问题的回答有关。 Anyone Have MediaPlayer Working with ParcelFileDescriptor and createPipe()?
当MediaRecorder试图写入标题信息时,管道可能会关闭。
如果您使用:
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
该记录工作正常,因为它没有标题信息,只有原始音频。