android和ios,音頻互通方案

jopen 9年前發布 | 25K 次閱讀 Android 移動開發

 

好久不更新博客上,從年前從公司辭職,這半年以來,一直靠做一些外包app養活自己!也算是達成了自己年前制定的目標!可是也想著總不能一直做外包吧,所以決定做一些自己覺得有意思的app,掛到應用商店上和app store上,只要有1-2k或者1-2w的活躍用戶,自己也就滿足了!

最近尋思做一個語音feed系統,難點呢,其實也就是在android和ios音頻互通上!忙了一個星期解決了這個問題,所以就和大家分享下!先說下整體的設計方案:

服務器:php

數據庫:redis

協議:http + json

客戶端 : android(java) + ios(oc)

在音頻的格式選擇問題上,猶豫了很久,這里其實有N個方案的,不過對于我這種非多媒體開發者來講,還是選擇一個最直接最能解決問題的就可以了!起初選擇的是amr,android一切都ok,但是在ios上,wav格式的音頻文件解析成amr格式的文件,或者amr格式的音頻文件解碼成wav格式的文件是總是出錯,用的是github上的libcoreamr庫,不明所以!當然如果誰解決了還是可以跟我聊下!

最終選擇了mp3的格式!缺點就是生成的音頻文件比amr文件要大!優點就是我解決了!哈哈

下面干貨代碼:首先是android 部分,相對比較簡單,就是通過mic錄制成mp3文件,然后上傳服務器!

錄音部分:其實就是對于MediaRecorder的使用,

recorder = new MediaRecorder();
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setOutputFile(fileName); try {
recorder.prepare();
} catch (IOException e) {

                }  
                recorder.start();
                Toast.makeText(AddActivity.this, "開始錄音", Toast.LENGTH_SHORT).show();</pre><br />

上傳服務器,用的是AsyncHttp庫,非常方便,這里注意的是對音頻文件的上傳格式問題,最好還是用文件上傳的格式,php也用$_FILES[""]去提取,不要用大家平時長傳圖片的形式,將文件轉換成byte[],再轉換成String,再給到php,php再保存文件到服務器,這樣極易破壞文件的格式!注意!

RequestParams params = new RequestParams();
                params.put("uid", SingleManager.user.getUid());
                params.put("textContent", content.getEditableText().toString());
                try 
                {
                    params.put("radioContent", new File(fileName) );
                }
                catch (FileNotFoundException e1)
                {
                    e1.printStackTrace();
                }

            AsyncHttpRequestClient.post(HttpUtil.postUrl, params ,new JSONObjectResponseHandler(AddActivity.this)
            {
                public void onJsonOk(JSONObject response)
                {
                    try 
                    {
                    } 
                    catch (Exception e) 
                    {

                    }

                    Toast.makeText( AddActivity.this, "發表成功", Toast.LENGTH_SHORT).show();
                    finish();
                } 

            });


        }</pre><br />

再就是ios部分了,這里先給出一個wav轉mp3的庫地址,https://github.com/rpplusplus/iOSMp3Recorder,其實就是AVAudioRecorder + lame!

錄制部分:對于AVAudioRecorder的使用和一些設置信息:

NSString *dir = [NSHomeDirectory() stringByAppendingPathComponent:@"documents"];
    audioFilePath = [NSString stringWithFormat:@"%@/testAudio.caf",dir];
    audioFileUrl = [NSURL fileURLWithPath:audioFilePath];

mp3FilePath = [NSString stringWithFormat:@"%@/mp3Audio.mp3",dir];
mp3FileUrl = [NSURL fileURLWithPath:mp3FilePath];


NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
[recordSettings setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey: AVFormatIDKey];
[recordSettings setValue :[NSNumber numberWithFloat:11025.0] forKey: AVSampleRateKey];//44100.0
[recordSettings setValue :[NSNumber numberWithInt:2] forKey: AVNumberOfChannelsKey];
[recordSettings setValue :[NSNumber numberWithInt:16] forKey: AVLinearPCMBitDepthKey];
[recordSettings setValue :[NSNumber numberWithInt:AVAudioQualityLow] forKey:AVEncoderAudioQualityKey];


recorder = [[AVAudioRecorder alloc] initWithURL:audioFileUrl settings:recordSettings error:nil];
recorder.delegate = self;
[recorder record];</pre><br />

轉碼部分:在錄制結束之后,要對錄制文件進行轉碼,轉換成mp3格式

@try {
        int read, write;

    FILE *pcm = fopen([audioFilePath cStringUsingEncoding:1], "rb");  //source 被轉換的音頻文件位置
    fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
    FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb");  //output 輸出生成的Mp3文件位置

    const int PCM_SIZE = 8192;
    const int MP3_SIZE = 8192;
    short int pcm_buffer[PCM_SIZE*2];
    unsigned char mp3_buffer[MP3_SIZE];

    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 11025.0);
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);

    do {
        read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
        if (read == 0)
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
        else
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

        fwrite(mp3_buffer, write, 1, mp3);

    } while (read != 0);

    lame_close(lame);
    fclose(mp3);
    fclose(pcm);
}
@catch (NSException *exception) {
    NSLog(@"%@",[exception description]);
}
@finally
{
}</pre><br />

最后是上傳服務器部分:這里使用的AFNETWORKING,ios常用的一個異步網絡庫,很好用,功能和android的aysncHttp庫類似,這里和android上傳使用的同一個php接口,所以音頻文件按照文件形式上傳,而不是轉換成NSData再上傳,容易破壞音頻格式!

SingleManager single = [SingleManager shareManager];
    AFHTTPRequestOperationManager manager = [AFHTTPRequestOperationManager manager];

NSString *uid = [NSString stringWithFormat:@"%d",single.user.userId];
NSString *textContent = self.textContent.text;

NSFileManager *fileManager = [NSFileManager defaultManager];
NSData *data = [fileManager contentsAtPath:mp3FilePath];

NSDictionary *parameters = @{@"uid":uid,@"textContent":textContent,@"radioContent":data};

[manager POST:[baseUrl stringByAppendingString:post] parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData){[formData appendPartWithFileURL:mp3FileUrl name:@"radioContent" error:nil];

}
      success:^(AFHTTPRequestOperation *operation, id responseObject)
{
     NSMutableDictionary *result = (NSMutableDictionary *)responseObject;
     NSLog(@"Result: %@",result);

     [self.navigationController popViewControllerAnimated:YES];
 }
      failure:^(AFHTTPRequestOperation *operation, NSError *error)
 {

 }];</pre><br />

最后是php部分,這里php做的工作比較簡單,就是得到客戶端上傳的文件,然后保存成mp3文件就可以了!還是給出部分代碼:

$body["rId"] = $rId;

$base_path = "../radio/"; //接收文件目錄
$target_path = $base_path .$rId.".mp3";
move_uploaded_file ( $_FILES ['radioContent'] ['tmp_name'], $target_path );

outPut($body);</pre>
剩下的播放部分就很簡單了,無論是android還是ios,只要使用系統提供的播放器,從服務器拿到mp3文件的url,就可以只接播放了,因為mp3是通用的音頻格式,無論是android還是ios都不需要做什么轉換!直接播放就ok!

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!