合并音频文件并在不同 API 版本中播放时出现奇怪的问题

发布于 2024-12-17 21:02:54 字数 2382 浏览 0 评论 0原文

所有,我正在使用媒体录音机来录制音频

案例 1:如果我使用安装了 Android 版本 2.2 的设备,我录制的音频会合并并播放得很好。

情况 2:如果我在 安装 Android 1.6 的设备中使用它,我将无法播放组合的音频文件。

它仅播放最先录制的音频,并且下一个录制的音频文件保持为空,没有声音

另外,我在 Logcat 中没有收到任何错误

我使用以下代码来录制音频:

    mRecorder = new MediaRecorder();
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
    mRecorder.setOutputFile(main_record_file);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mRecorder.prepare();
    mRecorder.start();

我还尝试了 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

组合音频文件的代码:

    public void createCombineRecFile(){
    combined_file_stored_path=getFilename_combined_raw(); // File path in String to store recorded audio
    byte fileContent[]=null;
    FileInputStream ins;
    FileOutputStream fos = null;
    try{
        fos = new FileOutputStream(combined_file_stored_path,true);
    }
    catch (FileNotFoundException e1){
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    for(int i=0;i<audNames.size();i++){
        try{
            File f=new File(audNames.get(i));
            Log.v("Record Message", "File Length=========>>>"+f.length());
            fileContent = new byte[(int)f.length()];
            ins=new FileInputStream(audNames.get(i));
            int r=ins.read(fileContent);// Reads the file content as byte from the list.
            Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
            fos.write(fileContent);//Write the byte into the combine file.

            Log.v("Record Message", "File======="+i+"is Appended");

        }
        catch (FileNotFoundException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try{
        fos.close();
        Log.v("Record Message", "===== Combine File Closed =====");
    }
    catch (IOException e){
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

让我知道需要的任何详细信息。谢谢。

All , I am using Media Recorder for Recording Audio.

Case 1: If i use Android Version 2.2 installed devices, my recorded audio combined and playing well.

Case 2: If i use it in Android 1.6 installed devices, i am not able to play the combined audio file.

It is playing only the very first recorded audio and next recorded audio files keep empty no sound.

Also i am not getting any error in Logcat.

I used following code for recording audio :

    mRecorder = new MediaRecorder();
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
    mRecorder.setOutputFile(main_record_file);
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    mRecorder.prepare();
    mRecorder.start();

Also i tried for mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);

Code for combining Audio file :

    public void createCombineRecFile(){
    combined_file_stored_path=getFilename_combined_raw(); // File path in String to store recorded audio
    byte fileContent[]=null;
    FileInputStream ins;
    FileOutputStream fos = null;
    try{
        fos = new FileOutputStream(combined_file_stored_path,true);
    }
    catch (FileNotFoundException e1){
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    for(int i=0;i<audNames.size();i++){
        try{
            File f=new File(audNames.get(i));
            Log.v("Record Message", "File Length=========>>>"+f.length());
            fileContent = new byte[(int)f.length()];
            ins=new FileInputStream(audNames.get(i));
            int r=ins.read(fileContent);// Reads the file content as byte from the list.
            Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
            fos.write(fileContent);//Write the byte into the combine file.

            Log.v("Record Message", "File======="+i+"is Appended");

        }
        catch (FileNotFoundException e){
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try{
        fos.close();
        Log.v("Record Message", "===== Combine File Closed =====");
    }
    catch (IOException e){
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Let me know any details need.Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦回旧景 2024-12-24 21:02:54

每个音频文件都有自己的标头(包括有关长度/样本等的信息) - 通过按照您的方式组合文件,生成的文件具有多个标头,每个源文件一个标头(取决于带有文件偏移量等的确切格式)。
因此,生成的文件在文件格式规范方面不正确。

较新的 Android 版本更加宽松,并且可以使用“多个标头”进行工作/播放...旧版本则不...

要创建正确组合的音频文件,您必须符合规范,这意味着创建一个新标头它描述了所有包含的音频...

使用不同的方法组合音频文件 - 例如通过 ffmpeg (请参阅 制作方法适用于 Android 的 ffmpeg)。

Every audio file has its own header (includes information about length/samples etc.) - by combining the files the way you do the resulting file has multiple headers, one per source file (depending on the exact format with file offsets etc.).
Thus the resulting file is NOT correct in terms of file format spec.

The newer Android version are more permissive and work/play with "multiple headers" present... the older versions do not...

To create a correctly combined audio file you must conform to the spec which among other things means creating one new header which describes all included audio...

Use for the the combination of audio files a different approach - for example via ffmpeg (see this for how to make ffmpeg for android).

一刻暧昧 2024-12-24 21:02:54

前言:还没有测试过这个,但我不明白为什么它不起作用。

如果标头是导致此问题的原因,那么您可以很轻松地解决它。使用您提供的代码,编码是 AMR-NB。根据 本文档,AMR 标头只是第一个6个字节,分别是0x23、0x21、0x41、0x4D、0x52、0x0A。如果后续文件中的标头导致问题,只需从后续文件中省略这些字节即可,例如

write all bytes of first file
write from byte[6] -> byte[end] of subsequent files

让我知道情况如何。

编辑:根据要求,将 try 块更改为:

try{
        File f=new File(audNames.get(i));
        Log.v("Record Message", "File Length=========>>>"+f.length());
        fileContent = new byte[(int)f.length()];

        ///////////////new bit////////

        //same as you had, this opens a byte stream to the file
        ins=new FileInputStream(audNames.get(i));
        //reads fileContent.length bytes
        ins.read(fileContent);
        //now fileContent contains the entire audio file - in bytes.
        if(i>0){
            //we are not writing the first audio recording, but subsequent ones
            //so we don't want the header included in the write

            //copy the entire file, but not the first 6 bytes
            byte[] headerlessFileContent = new byte[fileContent.length()-6];
            for(int j=6; j<fileContent.length();j++){
                headerlessFileContent[j-6] = fileContent[j];
            }
            fileContent = headerlessFileContent;
        }
        ////////////////////////////

        Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
        fos.write(fileContent);//Write the byte into the combine file.

        Log.v("Record Message", "File======="+i+"is Appended");

    }

Foreword: Haven't tested this, but I don't see why it shouldn't work.

Provided the headers ARE the cause of this problem, you can solve it really easily. Using the code you've given, the encoding is AMR-NB. According to this document the AMR header is simply the first 6 bytes, which are 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A. If the headers in subsequent files are causing the issue, simply omit those bytes from subsequent files e.g.

write all bytes of first file
write from byte[6] -> byte[end] of subsequent files

Let me know how it goes.

EDIT: At request, change the try block to:

try{
        File f=new File(audNames.get(i));
        Log.v("Record Message", "File Length=========>>>"+f.length());
        fileContent = new byte[(int)f.length()];

        ///////////////new bit////////

        //same as you had, this opens a byte stream to the file
        ins=new FileInputStream(audNames.get(i));
        //reads fileContent.length bytes
        ins.read(fileContent);
        //now fileContent contains the entire audio file - in bytes.
        if(i>0){
            //we are not writing the first audio recording, but subsequent ones
            //so we don't want the header included in the write

            //copy the entire file, but not the first 6 bytes
            byte[] headerlessFileContent = new byte[fileContent.length()-6];
            for(int j=6; j<fileContent.length();j++){
                headerlessFileContent[j-6] = fileContent[j];
            }
            fileContent = headerlessFileContent;
        }
        ////////////////////////////

        Log.v("Record Message", "Number Of Bytes Readed=====>>>"+r);
        fos.write(fileContent);//Write the byte into the combine file.

        Log.v("Record Message", "File======="+i+"is Appended");

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文