Android 如何以编程方式从.opus音频文件获取.m4a音频文件

Android 如何以编程方式从.opus音频文件获取.m4a音频文件,android,audio,m4a,opus,Android,Audio,M4a,Opus,我正在开发一个管理Whatsapp语音笔记的应用程序。 不久前,WhatsApp开始使用opus文件格式保存语音备忘,而不是像以前那样使用aac 我的应用程序获得一个URI(通过隐式意图),该URI指向存储在WhatsApp文件夹中的opus语音备忘 由于opus音频文件不可能在许多设备和应用程序中播放(例如Viber),因此我想在一个单独的文件中创建一个m4a格式的opus音频文件,该文件是我从WhatsApp获得的 我想做的是: 我使用ContentResolver和openInputStr

我正在开发一个管理Whatsapp语音笔记的应用程序。 不久前,WhatsApp开始使用opus文件格式保存语音备忘,而不是像以前那样使用aac

我的应用程序获得一个URI(通过隐式意图),该URI指向存储在WhatsApp文件夹中的opus语音备忘

由于opus音频文件不可能在许多设备和应用程序中播放(例如Viber),因此我想在一个单独的文件中创建一个m4a格式的opus音频文件,该文件是我从WhatsApp获得的

我想做的是: 我使用ContentResolver和openInputStream()在通过隐式意图获取的Uri表示的内容上获取InputStream。然后,我在我的应用程序文件夹中的一个文件上创建了一个FileOutputStream。 我使用了一条以“.m4a”结尾的路径,而不是“.opus”

像这样:

try {
                InputStream inputStream = getContentResolver().openInputStream(uriFromExternalIntent);
                String OUTPUT_DIRECTORY = Environment.getExternalStorageDirectory() + "/Audios/recordings/";


                boolean exists = (new File(OUTPUT_DIRECTORY)).exists();
                if (!exists) {
                    new File(OUTPUT_DIRECTORY).mkdirs();
                }

                Calendar c = Calendar.getInstance();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                String strDate = sdf.format(c.getTime());
                //Setting the output file complete final path
                String OUTPUT_FILE = OUTPUT_DIRECTORY + strDate + ".m4a";
                File outputFile = new File(OUTPUT_FILE);
                OutputStream out = null;
                try {
                    out = new FileOutputStream(outputFile);
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buf)) > 0) {
                        out.write(buf, 0, len);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (out != null) {
                            out.close();
                        }
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
通过将文件保存在API 24设备上以“.m4a”结尾的路径中,我可以在我的应用程序以及WhatsApp、Viber或Telegram等应用程序中播放该文件。 但在API23上,除了WhatsApp之外,每个应用程序都会出现相同的代码错误

总而言之,我正在寻找一种从指向.opus音频文件的URI以编程方式获取.m4a音频文件的方法

有一些应用程序能够做到这一点,而不显示任何类型的转换,所以我想有一个技巧可以轻松做到这一点,而不转换。
有什么建议吗?

用不同的扩展名复制文件肯定不是一种好办法

你有几个选择,这取决于你希望你的应用程序有多强大,以及你愿意投入多少工作

便宜而简单的方法是找到一个免费的在线文件转换工具,你可以尝试在你的应用程序中利用它。我不会费心去链接任何特定的服务,因为我不推荐这种方法。你的应用程序的稳定性将取决于你选择的服务。这很可能是可行的,但也很难看

更合理的方法是在应用程序中实际转换文件。最简单的方法是找到一个能够在目标格式和源格式之间转换的库。我不知道有任何Android/Java音频转换库,但我知道有一个叫做C的不错的库,它有几个Java包装器(例如,和)。第一个链接(Guardian项目)是为Android制作的,包括SoX和FFMpeg。它不是特别轻。第二个似乎不适用于Android,因此您可能需要自己寻找合适的二进制文件或构建SoX(提示:Guardian项目中的二进制文件位于“res/raw”中)。我查看了SoX以确认它支持Opus格式。另外,FFMpeg还支持Opus。在项目中适当地连接SoX或FFMpeg和Java包装器之后,您应该能够使用它们来转换文件。根据您的用例,您应该注意您选择使用的库的许可证


转换文件的困难方法是编写自己的编解码器。您可以使用该类在Android Java中实现这一点,但Android不理解Opus(据我所知),因此这不是一个简单的尝试。我怀疑你是否想走这条路。

用不同的扩展名复制文件肯定不是一条路

你有几个选择,这取决于你希望你的应用程序有多强大,以及你愿意投入多少工作

便宜而简单的方法是找到一个免费的在线文件转换工具,你可以尝试在你的应用程序中利用它。我不会费心去链接任何特定的服务,因为我不推荐这种方法。你的应用程序的稳定性将取决于你选择的服务。这很可能是可行的,但也很难看

更合理的方法是在应用程序中实际转换文件。最简单的方法是找到一个能够在目标格式和源格式之间转换的库。我不知道有任何Android/Java音频转换库,但我知道有一个叫做C的不错的库,它有几个Java包装器(例如,和)。第一个链接(Guardian项目)是为Android制作的,包括SoX和FFMpeg。它不是特别轻。第二个似乎不适用于Android,因此您可能需要自己寻找合适的二进制文件或构建SoX(提示:Guardian项目中的二进制文件位于“res/raw”中)。我查看了SoX以确认它支持Opus格式。另外,FFMpeg还支持Opus。在项目中适当地连接SoX或FFMpeg和Java包装器之后,您应该能够使用它们来转换文件。根据您的用例,您应该注意您选择使用的库的许可证


转换文件的困难方法是编写自己的编解码器。您可以使用该类在Android Java中实现这一点,但Android不理解Opus(据我所知),因此这不是一个简单的尝试。我怀疑你是否愿意走这条路。

谢谢你@Dave,我将进一步研究这些图书馆。出于好奇:当我复制扩展名为.m4a的.opus文件时,API 24上的一切工作正常吗?它是否能够在不更改扩展名的情况下在API 24上播放.opus文件?我的第一个想法是,它能够播放Opus格式,并查看文件数据以确定它是什么类型的文件,而不是扩展名。在API 24上,当我从应用程序共享到Viber或用.m4a扩展名发送Opus音频时,我能够在聊天室中的两个应用程序上播放它。相反,当文件扩展名为.opus时,两个应用程序都会要求外部opus播放器播放该文件(因此扩展名似乎是相关的)。但同样的事情在API 23上不起作用:当我尝试在Vib上打开扩展名为.m4a的opus文件时