MediaRecorder 捕获的音频文件在使用 Retrofit 2 发送到服务器后损坏

Audio file captured by MediaRecorder is broken after it is sent to server using Retrofit 2

我的应用程序录制了一个音频剪辑,并在录制后使用 Retrofit2 将剪辑发送到服务器 completed.The 服务器收到文件,但文件已损坏,我所说的损坏的意思是它不能被播放。我使用以下 URL(示例 url:mydomain.co/audio/myaudio.mp4)播放音频片段,我尝试使用 postman 与另一个音频文件一起播放,音频文件可以播放 successfully.Besides,甚至通过Filezilla下载android捕获的音频片段也有同样的损坏文件。

这是我录制音频的方式:

private void startRecordingAudio() {
    Log.d("audiorecording","recording sound");
    recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    recorder.setAudioEncodingBitRate(16);
    recorder.setAudioSamplingRate(44100);

    MediaFileHelper fileHelper = new MediaFileHelper();
    audioOutputFile = fileHelper.getOutputAudioFile();
    recorder.setOutputFile(audioOutputFile.getAbsolutePath());

    try {
        recorder.prepare();
        recorder.start();
    } catch (IllegalStateException | IOException e) {
        e.printStackTrace();
    }
}

这里是音频文件的文件路径:

/storage/emulated/0/DCIM/myapp/AUDIO_20171023143717.mp4

为了解决这个问题,我尝试使用不同的编解码器和不同的输出格式,如下

recorder.setOutputFormat(MediaRecorder.OutputFormat.THERE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

recorder.setOutputFormat(MediaRecorder.OutputFormat.THERE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);

我也尝试将文件扩展名更改为 .mp3.mp4.3gpp ,但其中 none 似乎在服务器端工作. 为了清楚起见,我附上了用于使用 Retrofit2:

将音频文件发送到服务器的代码
private void sendAudioToServer( final String audioFilePath,final String api_key){
    Log.d("AUDIO FILE PATH",audioFilePath);
    File audioFile = new File(audioFilePath);
    RequestBody audioBody = RequestBody.create(MediaType.parse("audio/*"), audioFilePath);
    MultipartBody.Part aFile = MultipartBody.Part.createFormData("audio", audioFile.getName(), audioBody);

    OkHttpClient httpClient = new OkHttpClient.Builder()
            .addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    okhttp3.Request.Builder ongoing = chain.request().newBuilder();
                    ongoing.addHeader("authorization", api_key);
                    return chain.proceed(ongoing.build());
                }
            })
            .build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(AppConfig.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient)
            .build();

    AudioInterface audioInterface = retrofit.create(AudioInterface.class);
    Call<ResultObject> serverCom = audioInterface.sendAudioToServer(aFile);

    serverCom.enqueue(new Callback<ResultObject>() {
        @Override
        public void onResponse(Call<ResultObject> call, retrofit2.Response<ResultObject> response) {
            ResultObject result = response.body();
            if(!TextUtils.isEmpty(result.getSuccess())){
                Log.d("audio Result " , result.getSuccess());
            }
        }

        @Override
        public void onFailure(Call<ResultObject> call, Throwable t) {
            Log.d("audio error",t.toString());
        }
    });
}

我的问题是:

1)从 android 向服务器发送音频文件的正确方法是什么?

2) 如果问题是关于录音机的编解码器,那么音频文件的正确编解码器是什么?因为稍后我需要支持相同的音频 Ios 和网站..

有人请提前给一些suggestion.Thanks

编辑:

我尝试用MediaPlayer播放录制的音频文件,文件路径是这样的

/storage/emulated/0/DCIM/Myapp/AUDIO_20171026135950.mp4

这是我播放上面音频文件的代码

String audioFile = " /storage/emulated/0/DCIM/Myapp/AUDIO_20171026135950.mp4";
audioButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        MediaPlayer mp = new MediaPlayer();
                        Uri uri = Uri.parse(audioFile);
                        try{
                            mp.setDataSource(mContext,uri);
                            mp.prepare();
                            mp.start();
                        }catch (IOException E){
                            E.printStackTrace();
                        }
                    }
                });

但是当我播放本地音频文件时抛出以下异常:

W/MediaPlayer: Couldn't open file on client side; trying server side: java.io.FileNotFoundException: No content provider: /storage/emulated/0/DCIM/Myapp/AUDIO_20171026135950.mp4

如果我从服务器播放URL,它会抛出这个异常:

10-26 14:06:05.551 8806-8806/? W/System.err: java.io.IOException: Prepare failed.: status=0x1
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.media.MediaPlayer._prepare(Native Method)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.media.MediaPlayer.prepare(MediaPlayer.java:1163)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.view.View.performClick(View.java:5198)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.view.View$PerformClick.run(View.java:21147)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.os.Looper.loop(Looper.java:148)
10-26 14:06:05.552 8806-8806/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
10-26 14:06:05.552 8806-8806/? W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
10-26 14:06:05.552 8806-8806/? W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
10-26 14:06:05.552 8806-8806/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

那么我做错了什么?

你的setAudioEncodingBitRate很低。

16hz 应该是 16000 而不仅仅是 16

setAudioEncodingBitRate 值中的 16000 或 32000 试试

如果有效或无效,请在此处评论,我会尽力帮助您