Как программно получить аудиофайл .m4a из аудиофайла .opus

Я разрабатываю приложение, которое управляет голосовыми заметками WhatsApp. Некоторое время назад WhatsApp начал сохранять голосовые заметки, используя формат файла opus вместо aac, как раньше.

Мое приложение получает URI (через неявное намерение), который указывает на голосовую заметку opus, хранящуюся в папке WhatsApp.

Поскольку аудиофайлы opus невозможно воспроизвести на многих устройствах и во многих приложениях (например, Viber), я хотел бы создать в отдельном файле версию формата m4a opus аудиофайл, который я получил от WhatsApp.

Я пытался сделать следующее: я использовал ContentResolver и openInputStream (), чтобы получить InputStream для содержимого, представленного Uri, которое я получил через неявное намерение. Затем я создал 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();
                    }
                }

Сохраняя файл по пути, который заканчивается на «.m4a» на устройствах с API 24, я могу воспроизводить файл внутри своего приложения и в таких приложениях, как WhatsApp, Viber или Telegram. Но в API 23 один и тот же код выдает ошибки во всех приложениях, кроме WhatsApp.

Напомним, я ищу способ программно получить аудиофайл .m4a из URI, который указывает на аудиофайл .opus.

Есть некоторые приложения, которые могут делать это без какого-либо преобразования, поэтому я думаю, что есть трюк, позволяющий легко сделать это без преобразования. Любой совет?


person Diego    schedule 10.09.2017    source источник


Ответы (1)


Копирование файла с другим расширением определенно не лучший вариант.

У вас есть несколько вариантов в зависимости от того, насколько надежным вы хотите, чтобы ваше приложение было и сколько работы вы готовы вложить.

Самый дешевый и простой путь - найти бесплатный онлайн-инструмент для преобразования файлов, которым вы можете попробовать воспользоваться в своем приложении. Я не буду связывать какую-либо конкретную услугу, потому что я не рекомендую такой подход. Ваше приложение будет зависеть от выбранного вами сервиса из-за его стабильности. Скорее всего, это выполнимо, но при этом очень некрасиво.

Более разумный подход состоит в том, чтобы фактически преобразовать файл в вашем приложении. Самый простой способ сделать это - найти библиотеку, способную конвертировать между целевым и исходным форматами. Я не знаю каких-либо библиотек для преобразования звука Android / Java, но я знаю приличную библиотеку C под названием SoX, в котором доступно несколько оболочек Java (например, здесь и здесь). Первая из этих ссылок (проект Guardian) предназначена для Android и включает как SoX, так и FFMpeg. Он не особо легкий. Второе, похоже, не для Android, поэтому вам может потребоваться поиск подходящего двоичного файла или самостоятельная сборка SoX (подсказка: двоичные файлы в Guardian Project находятся в «res / raw»). Я посмотрел на SoX, чтобы убедиться, что он поддерживает формат Opus. Кстати, FFMpeg также поддерживает Opus. Как только вы правильно подключите SoX или FFMpeg и оболочку Java к вашему проекту, вы сможете использовать их для преобразования файлов. В зависимости от вашего варианта использования вам следует обращать внимание на лицензии библиотек, которые вы выбираете для использования.

Сложный способ преобразовать файл - написать собственный кодек. Вы могли бы сделать это в Android Java с помощью класса MediaCodec, но Android MediaExtractor не понимает Opus (насколько я знаю ), так что это будет непростая задача. Я сомневаюсь, что ты хочешь пойти по этому пути.

person Dave    schedule 10.09.2017
comment
Спасибо @Dave, я буду дальше изучать эти библиотеки. Просто из любопытства: как это возможно, что когда я копирую файл .opus с расширением .m4a, все работает нормально на API 24? - person Diego; 12.09.2017
comment
Может ли он воспроизводить файлы .opus на API 24 без изменения расширения? Моя первая мысль заключается в том, что он способен воспроизводить формат Opus и смотрит на данные файла, чтобы определить, какой это тип файла, а не расширение. - person Dave; 12.09.2017
comment
на API 24, когда я делюсь из своего приложения в Viber или Telegram аудио opus с расширением .m4a, я могу воспроизводить его в обоих приложениях прямо в чате. Вместо этого, когда файл имеет расширение .opus, оба приложения запрашивают внешний проигрыватель opus для воспроизведения файла (так что расширение кажется очевидным). Но то же самое не работает с API 23: когда я пытаюсь открыть файл opus с расширением .m4a в Viber / Telegran на API 23, я получаю «Невозможно воспроизвести этот тип звука». Я не могу понять причину этой разницы между API 23 и 24, версия приложения на двух устройствах абсолютно одинакова. - person Diego; 12.09.2017
comment
Для меня это звучит (и это всего лишь предположение), что Viber и Telegram смотрят только на расширение файла, поэтому достаточно изменить расширение, чтобы они были счастливы. Тогда медиаплеер на вашем устройстве API 24 не заботится о расширении, но понимает формат Opus. - person Dave; 12.09.2017
comment
Кстати, Android якобы поддерживает формат Opus в контейнере Matroska (.mkv), начиная с API 21, согласно страница поддерживаемых форматов. Расширение .opus относится к формату Opus в контейнере Ogg. Я не знаю, почему устройство API 24 понимает .opus, если это не какая-то настройка производителя или случайный случай. Хотя, поскольку медиаплеер должен понимать Ogg (поддерживается Ogg Vorbis) и кодек Opus, я не могу объяснить, почему он не распознает .opus. - person Dave; 12.09.2017