经过一番折腾,终于找到了一种第三方库来转换android与iOS录音播放格式不兼容的问题。
思路:android/iOS手机录音传给服务器,参数(录音数据+手机端口类型),然后等到服务器广播数据给玩家,判断端口是android,将数据保存为为.amr格式,否则保存为.aac格式。不同手机端口调用相应端口函数。
1、设置端口录音格式:
android–>.amr
public void record(){
if (isRecording == true ) return;
recondPath = Environment.getExternalStorageDirectory().getAbsolutePath();
recondPath += "/ione1.amr"; //录音格式
File dirs = new File(recondPath);
if (dirs.exists()){
dirs.delete();
}
stopRecorder();
isRecording = true;
mRecorder = new MediaRecorder();
//设置音源为Micphone
mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
//设置封装格式
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
//设置编码格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder. setAudioEncodingBitRate(8);//设置音频编码录音比特率
mRecorder.setAudioChannels(1);//设置录制的音频通道数
mRecorder.setAudioSamplingRate(8000); //设置音频采样率记录
mRecorder.setOutputFile(recondPath);
try {
mRecorder.prepare();
} catch (IOException e) {
Log.e(TAG,"prepare() Failed");
}
//录音
mRecorder.start();
}
public boolean stopRecorder() {
if( mRecorder == null ) return false;
try{
mRecorder.stop();
mRecorder.reset();
mRecorder.release();
mRecorder = null;
}catch ( IllegalStateException e){
e.printStackTrace();
}
return false;
}
ios–>.aac
-(void)startAudioRecording
{
if(!isRecording)
{
[self init];
isRecording = YES;
NSLog(@"正在录音");
NSMutableDictionary *dicM=[NSMutableDictionary dictionary];
//设置录音格式
[dicM setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];//录音格式
//设置录音采样率,8000是电话采样率,对于一般录音已经够了
[dicM setObject:@(1600) forKey:AVSampleRateKey];
//设置通道,这里采用单声道
[dicM setObject:@(1) forKey:AVNumberOfChannelsKey];
//每个采样点位数,分为8、16、24、32
[dicM setObject:@(8) forKey:AVLinearPCMBitDepthKey];
//录音的质量
[dicM setValue:[NSNumber numberWithInt:AVAudioQualityMin] forKey:AVEncoderAudioQualityKey];
//是否使用浮点数采样
[dicM setObject:@(YES) forKey:AVLinearPCMIsFloatKey];
recorder = [[AVAudioRecorder alloc] initWithURL:recordedFile settings:dicM error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[self setSoundSession];
[recorder peakPowerForChannel:0];
[recorder prepareToRecord];
[recorder record];
}
}
2、接收服务器传来的需要播放的录音数据,根据不同端口录的音保存为数据相同录音格式:
android–>.amr
ios–>.aac
//服务器传来录音数据,保存在表voiceTab中 //voiceTab[index] = event.data
function MainScene:startPlayVoice()
if self.isStartRecond == false then -- 没有在录音
if device.platform == "android" or device.platform == "ios" then --播放录音
local len = #voiceTab
if len >= 1 then
voicePlay( data )
else
print(" 录音播放完了 ")
end
end
end
end
function voicePlay(data)
if device.platform == "android" then
local function callback(result)
-- print("录音播放完成 " )
ReturnRecordingPlayChange(result)
end
local path = writefileCheckRecond( data.voicebin,data.content )
print("开始播放了 voicePlay ")
local args = { 1,path,callback }
local sigs = "(ILjava/lang/String;I)I"
local luaj = require "cocos.cocos2d.luaj"
local className = "com/cocos2dx/sample/LuaJavaBridge"
local ok,ret = luaj.callStaticMethod(className,"sendLuaToJavaAudioRecorPlay",args,sigs)
if not ok then
print("luaj error:",ret)
else
print("The ret is:",ret)
end
elseif device.platform == "ios" then
local path = writefileCheckRecond( data.voicebin,data.content )
print("开始播放了 voicePlay ",path)
local i = iosAudioStartPlay( path )
end
end
function writefileCheckRecond( data,platform )
local path = device.writablePath.."netSprite/" --获取本地存储目录
if not io.exists(path) then
lfs.mkdir(path) --目录不存在,创建此目录
end
if platform == "android" then
path = path.."recond.amr"
elseif platform == "ios" then
path = path.."recond.aac"
else
return;
end
print("写入完成:"..path)
return path;
end
3、分析两端口录音互相播放的情况(A端口录音–>B端口播放)
android–>android:android玩家录音为.amr传给服务器,android玩家接收录音二进制数据保存的也是.amr格式,播放OK。
public void startPlay(String filePath,int luaFunc){
if( isPlay == true)
{
Log.d("tag","正在播放中");
return;
}
try {
stopPlay();
isPlay = true;
playLuaFun = luaFunc;
mPlayer = MediaPlayer.create(Cocos2dxActivity.getInstance(),Uri.parse(filePath));
mPlayer.start();// 开始播放
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){
@Override
public void onCompletion(MediaPlayer m) {
Log.d("tag","播放完毕");
LuaJavaBridge.callbackLuaFun("1","ReturnRecordingPlayChange",index++);
buySuccessJava(1);
Log.d(TAG,"playLuaFun = " + playLuaFun);
isPlay = false;
stopPlay();
}
});
}catch(Exception e){
Log.e(TAG,"prepare() Failed");
}
}
android–>iOS:android玩家录音为.amr传给服务器,iOS玩家接收录音二进制数据保存为.amr格式,调用第三方库将格式.amr转.mav格式就播放OK。
-(void)playAudio
{
if(!isPlay)
{
if([player isPlaying])
{
NSLog(@"停止录音播放");
[player pause];
}
else
{
NSString *documentsDirectory= [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
audioRecoderSavePath=[NSString stringWithFormat:@"%@/%@",documentsDirectory,@"netSprite/"];
recoderName= [NSString stringWithFormat:@"%@",@"recond.amr"];
tempRecoderPath=[NSString stringWithFormat:@"%@%@",audioRecoderSavePath,recoderName];
fm = [NSFileManager defaultManager]; //创建文件管理对象
if([fm fileExistsAtPath:tempRecoderPath] == NO)//判断文件是否存在
{
NSLog(@"文件不存在");
recoderName= [NSString stringWithFormat:@"%@",@"recond.aac"];
tempRecoderPath=[NSString stringWithFormat:@"%@%@",recoderName];
isIos = true;
[self startPlayAudio];
return;
}
else
{
isIos = false;
NSLog(@"文件存在");
}
NSString *recoderWavName= [NSString stringWithFormat:@"%@",@"recond.wav"];
tempWavRecoderPath =[NSString stringWithFormat:@"%@%@",recoderWavName];
//第三方库AudioConverter
[AudioConverter convertAmrToWavAtPath:tempRecoderPath wavSavePath:tempWavRecoderPath asynchronize:YES completion:^(BOOL success,NSString * _Nullable resultPath) {
if (success) {
NSLog(@"amr转wav成功!");
_wavFilePath = resultPath;
[self startPlayAudio];
} else {
NSLog(@"amr转wav失败!");
}
}];
}
}
}
iOS –>android:ios玩家录音为.aac格式传给服务器,android玩家接收录音二进制数据保存为.aac格式,
android玩家播iOS录的.aac格式OK。
iOS–>iOS:ios玩家录音为.aac格式传给服务器,ios玩家接收录音二进制数据保存为.aac格式,ios玩家播iOS录的.aac格式OK。
参考:
http://www.jb51.cc/article/p-mcdpwusb-bpt.html
http://blog.csdn.net/adalu1986/article/details/50502387
http://www.jianshu.com/p/7dc01b48f8fc