Фон
Мы хотим, чтобы пользователь мог выбрать видео из любого приложения, а затем обрезать видео максимум до 5 секунд.
Проблема
Чтобы получить Uri, который мы выбрали, он работает нормально (доступно решение здесь ).
Что касается самой обрезки, мы не смогли найти ни одной хорошей библиотеки, которая имеет разрешительную лицензию, за исключением одной под названием "k4l-video-trimmer" .Например, библиотека «FFmpeg» считается недопустимой, поскольку она использует GPLv3, что требует, чтобы приложение, использующее ее, также было открытым исходным кодом.Кроме того, как я читал, это занимает довольно много (около 9 МБ).
К сожалению, эта библиотека (k4l-video-trimmer) очень старая и не обновлялась годами, поэтому мне пришлосьраскошелитесь ( здесь ), чтобы справиться с этим красиво.Для обрезки используется библиотека с открытым исходным кодом "mp4parser" .
Проблема в том, что эта библиотека может обрабатывать только файлы, а неUri
или InputStream
, поэтому даже образец может аварийно завершить работу при выборе элементов, которые недоступны, как обычный файл, или даже иметь пути, которые он не может обработать.Я знаю, что во многих случаях возможно получить путь к файлу, но во многих других случаях это не так, и я также знаю, что можно просто скопировать файл ( здесь ), но это не очень хорошее решение, так как файл может быть большим и занимать много места, даже если он уже доступен.
Что я пробовал
Есть 2указывает, что библиотека использует файл:
В файле "K4LVideoTrimmer", в функции "setVideoURI", которая просто получает размер файла, который будет показан.Здесь решение довольно простое, основанное на документации Google :
public void setVideoURI(final Uri videoURI) {
mSrc = videoURI;
if (mOriginSizeFile == 0) {
final Cursor cursor = getContext().getContentResolver().query(videoURI, null, null, null, null);
if (cursor != null) {
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
cursor.moveToFirst();
mOriginSizeFile = cursor.getLong(sizeIndex);
cursor.close();
mTextSize.setText(Formatter.formatShortFileSize(getContext(), mOriginSizeFile));
}
}
...
В файле "TrimVideoUtils", в файле "startTrim", которыйвызывает функцию "genVideoUsingMp4Parser".Там она вызывает библиотеку «mp4parser», используя:
Movie movie = MovieCreator.build(new FileDataSourceViaHeapImpl(src.getAbsolutePath()));
Она говорит, что они используют FileDataSourceViaHeapImpl
(из библиотеки «mp4parser»), чтобы избежать OOM на Android, поэтому я решил остаться с ней.
Дело в том, что для этого существует 4 CTORS, все ожидают некоторого изменения файла: File, filePath, FileChannel, FileChannel + fileName.
Вопросы
- Есть ли способ преодолеть это?
Может быть, реализовать FileChannel
и моделировать реальный файл, используя ContentResolver
и Uri
?Я предполагаю, что это возможно, даже если это означает повторное открытие InputStream при необходимости ...
Чтобы увидеть, что я получил, вы можете клонировать проект здесь .Просто знайте, что это не делает никакой обрезки, поскольку код для этого в файле "K4LVideoTrimmer" прокомментирован:
//TODO handle trimming using Uri
//TrimVideoUtils.startTrim(file, getDestinationPath(), mStartPosition, mEndPosition, mOnTrimVideoListener);
Возможно, есть лучшая альтернатива этой библиотеке обрезки, которая также является разрешающей (например, имеется в виду лицензии Apache2 / MIT)?Тот, у которого нет этой проблемы?Или, может быть, даже что-то из самого Android Framework?Я думаю, что класс
MediaMuxer мог бы помочь (как написано
здесь ), но я думаю, что для этого может потребоваться API 26, в то время как нам нужно обрабатыватьAPI 21 и выше ...
РЕДАКТИРОВАТЬ:
Я думал, что нашел решение, используя другое решение для обрезки себя, и написал об этом здесь , но, к сожалению, он не может обрабатывать некоторые входные видео, в то время как библиотека mp4parser
может обрабатывать их.
Пожалуйста, дайте мне знать, если возможно изменить mp4parser
обрабатывать такие входные видео, даже если они из Uri, а не из File (без обходного пути простого копирования в видеофайл).