【发布时间】:2019-02-03 13:25:20
【问题描述】:
背景
我们想让用户从任何应用程序中选择一个视频,然后将视频修剪为最长 5 秒。
问题
为了让 Uri 被选中,我们让它工作正常(解决方案可用here)。
至于修剪本身,我们找不到任何具有许可许可证的好库,除了一个名为 "k4l-video-trimmer" 的库。例如,库“FFmpeg”被认为是未经许可的,因为它使用 GPLv3,这要求使用它的应用程序也必须是开源的。此外,正如我所读到的,它需要很多(大约 9MB)。
遗憾的是,这个库 (k4l-video-trimmer) 已经很老了,而且很多年都没有更新,所以我不得不分叉它 (here) 才能很好地处理它。它使用一个名为"mp4parser" 的开源库来进行修剪。
问题是,这个库似乎只能处理文件,而不是 Uri 或 InputStream,所以即使是示例在选择像普通文件一样无法访问的项目时也会崩溃,甚至有它无法处理的路径。我知道在很多情况下可以获得文件的路径,但在很多其他情况下,它不是,而且我也知道可以只复制文件(here),但这不是一个好解决方案,因为文件可能很大并且占用大量空间,即使它已经可以访问。
我尝试过的
库使用文件的地方有 2 个:
-
在“K4LVideoTrimmer”文件中,在“setVideoURI”函数中,它只是获取要显示的文件大小。这里的解决方案很简单,基于Google's documentation:
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”文件中,在调用“genVideoUsingMp4Parser”函数的“startTrim”中。在那里,它使用以下方法调用“mp4parser”库:
Movie movie = MovieCreator.build(new FileDataSourceViaHeapImpl(src.getAbsolutePath()));它说他们使用
FileDataSourceViaHeapImpl(来自“mp4parser”库)来避免Android上的OOM,所以我决定继续使用它。问题是,它有 4 个 CTOR,都期望文件有一些变体:File、filePath、FileChannel、FileChannel+fileName。
问题
- 有没有办法克服这个问题?
也许实现FileChannel 并使用ContentResolver 和Uri 模拟真实文件?我想这可能是可能的,即使这意味着在需要时重新打开 InputStream...
为了看看我做了什么,你可以克隆项目here。只知道它不做任何修剪,因为它在“K4LVideoTrimmer”文件中的代码被注释了:
//TODO handle trimming using Uri
//TrimVideoUtils.startTrim(file, getDestinationPath(), mStartPosition, mEndPosition, mOnTrimVideoListener);
- 这个修剪库是否有更好的替代方案,它也是允许的(例如 Apache2/MIT 许可证的含义)?没有这个问题的?或者甚至可能是 Android 框架本身的东西?我认为MediaMuxer 类可能会有所帮助(如here 所写),但我认为它可能需要 API 26,而我们需要处理 API 21 及更高版本...
编辑:
我想我已经找到了一个解决方案,通过使用不同的解决方案来修剪自己,并写了here,但遗憾的是它无法处理一些输入视频,而mp4parser 库可以处理它们。
请让我知道是否可以修改 mp4parser 以处理此类输入视频,即使它来自 Uri 而不是文件(没有仅复制到视频文件的解决方法)。
【问题讨论】:
-
API 18 Onwards 支持您提到的 MediaMuxer 类 [developer.android.com/reference/android/media/MediaMuxer].而答案stackoverflow.com/a/44653626/878126指的是Lollipop,也就是API21。我相信你可以轻松使用它!此外,如果您有 URI,那么围绕它创建一个 File 对象并将其传递给库进行处理有什么问题?你试过这个吗?如果您这样做了,响应/错误/问题是什么?
-
@RahulShukla 我发现的代码有效(它来自 API 18,顺便说一句,而不是链接上的 21),但仅适用于某些输入文件。对于其他一些人,它引发了异常,我在这里写了:stackoverflow.com/q/54573454/878126。你可以在这里查看我为此制作的 POC:github.com/AndroidDeveloperLB/VideoTrimmer。至于使用来自 Uri 的文件,这并不总是可能的。示例来自 Google Drive 应用程序。我目前的解决方案同时使用了这两种方法,但仍然会失败:(
标签: android inputstream android-contentresolver filechannel mp4parser