背景:
我正在开发一个Android移动应用程序,用户在应用程序中录制音频,然后将其上传到服务器,然后将其传输回社区。
到目前为止,我们已经使用.WAV格式,它可以输出相当大的文件大小,以便通过移动网络上传和流式传输。我正在努力转换为.AAC格式,但我已经了解了不同制造商发生的一些不同问题。
的问题:
然后这是主要问题。将文件流式传输到音频播放器时,声音播放器无法解码仅在三星设备上录制的音频。摩托罗拉和Nexus手机上录制的AAC文件可与之前的WAV文件完美互换。我可以直接在桌面上播放声音文件,如果我直接在网络浏览器中打开文件,它们都会播放。
当我使用AudioContext对音频进行流式处理和解码时会发生此问题。我认为这个问题与三星音频编解码器缺少标题数据有关,但我已经在这个问题上投入了大量时间,并且还没有找到可行的解决方案。这个问题似乎很简单,但我需要做很多工作才能确切地找出问题所在。任何帮助深表感谢。
我看到的两种方法是: 1.修复Android应用程序中源代码的编码问题 2.纠正浏览器中的错误。我看过有关使用函数尝试重新同步流的帖子,但我不完全了解如何实现这一点。
我认为最好的解决方案是#1。
我在浏览器中下载了两个示例文件,并查看了原始数据以进行比较。 (原始数据的快照http://i.imgur.com/tF6uHoO.png //我没有足够的声誉嵌入图片,但稍后会修改。)
在Android中录制代码 RecordActiviy.java
// FILE NAME
mFileName = "file.mp4";
// INITIATE MEDIA RECORDER
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setAudioSamplingRate(48000);
mRecorder.setAudioEncodingBitRate(64000);
try {
mRecorder.prepare();
mRecorder.start();
} catch (IOException e) {
Log.e("AUDIO RECORDING", "prepare() failed");
e.printStackTrace();
}
}
...
getSound.php
...
$File = $path . $filename;
switch($filetype){
case 'wav':
//FILE TYPE WAV
$mime_type = "audio/vnd.wave";
header("Content-type: ".$mime_type);
$test = readfile($file);
break;
case 'mp4':
//FILE TYPE MP4
//$mime_type = "audio/mp4";
$mime_type = "audio/aac";
header("Content-type: ".$mime_type);
$test = readfile($file);
break;
default:
break;
}
soundPlayer.js
...
var player;
function loadPlayer() {
player = new SoundPlayer();
..UI and other stuff..
}
// Build Sound Player Object
function SoundPlayer() {
this.arrayBuffer = null; //array buffer of audio data
this.context = new AudioContext(); //browser sound context
this.duration = null; //Length of audio clip
this.source = null; //Converted audio source
this.trueEnd = true; //Check to see if sound ended due to completion
this.isPlaying = false; //Check to see if sound is currently playing
this.t = 0; //Update variable for time counter
this.startTime = null; //Start time of audio is logged when playAudio()
this.byteData = null;
var sp = this; // sp = soundPlayer (Reference to SoundPlayer obj)
this.playAudio = function() {
this.source = null;
/* ArrayBuffer must be decoded each time play is called
* due to the nature of a decoded AudioBuffer only
* being able to be played once */
sp.context.decodeAudioData(sp.arrayBuffer, decoded);
sp.t = setInterval(updateProgress, 10);
};
this.loadSound = function(pid) {
$.ajax({
async: true,
url: "getSound.php",
data: { soundID: sID },
beforeSend: function(xhr) {
//Allow for binary data
xhr.overrideMimeType("text/plain; charset=x-user-defined");
},
success: function(dataAsString) {
dataAsString = dataAsString.trim();
if( dataAsString.localeCompare("") == 0 ){
alert("Sound File Not Found");
return;
}
// convert string to byte array
var bytes = [];
var i, l = dataAsString.length;
for (i = 0; i < l; ++i) {
bytes.push(dataAsString.charCodeAt(i) & 0xFF);
}
sp.byteData = bytes;
//Convert byte array into audio buffer
var arrayBuffer = new ArrayBuffer(bytes.length);
var bufferView = new Uint8Array(arrayBuffer);
for (var i = 0; i < bytes.length; i++) {
bufferView[i] = bytes[i];
}
sp.arrayBuffer = arrayBuffer;
//get sound duration info
sp.context.decodeAudioData(arrayBuffer, function(buffer) {
sp.duration = buffer.duration;
notify_UI_load_complete();
}, function(error){
**** // WE GET TO THIS BLOCK IN THE BROWSER
**** // RETURNS UNDEFINED
console.log("error decoding "+ arrayBuffer.length);
console.log(arrayBuffer);
console.log("error type "+ error);
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("load error");
console.log(textStatus, errorThrown);
alert("Could not load specific sound file");
}
});
}
...
TL; DR Web Audio AudioContext中的Android Samsung AAC音频流错误。网络音频很难。我们是否可以获得通用标准。
答案 0 :(得分:-1)
音频文件具有元数据信息。在某些文件中,它出现在文件末尾。在这种情况下,这些文件只能在完全下载时播放,即无法播放。
要使这些文件可流式化,您需要将该元数据信息移动到音频文件的开头。你可以使用MP4Box:
MP4Box -v -inter 300 old.mp4 -out new.mp4
其中300是以毫秒为单位的交错。