我们希望让用户从任何应用中选择视频,然后将视频剪裁为最多5秒.
为了让Uri被选中,我们让它工作正常(这里有解决方案).
至于修剪本身,我们找不到任何具有许可许可的好图书馆,除了一个名为"k4l-video-trimmer"的图书馆.例如,库"FFmpeg"被认为是非许可,因为它使用GPLv3,这要求使用它的应用程序也是开源的.此外,正如我所读,它需要相当多(约9MB).
可悲的是,这个库(k4l-video-trimmer)很老了,多年没有更新了,所以我不得不把它(这里)分叉,以便很好地处理它.它使用一个名为"mp4parser"的开源库来进行修剪.
问题是,这个库似乎只能处理文件,而不是一个Uri或者InputStream,所以即使样本在选择像普通文件一样无法访问的项目时也会崩溃,甚至还有无法处理的路径.我知道在很多情况下可以获得文件的路径,但在许多其他情况下,它不是,我也知道可以只复制文件(这里),但这不是一个好的解决方案,因为文件可能很大并占用大量空间,即使它已经可以访问.
库有两个地方使用文件:
在"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));
}
}
...
Run Code Online (Sandbox Code Playgroud)在"TrimVideoUtils"文件中,在"startTrim"中调用"genVideoUsingMp4Parser"函数.在那里,它使用以下方法调用"mp4parser"库:
Movie movie = MovieCreator.build(new FileDataSourceViaHeapImpl(src.getAbsolutePath()));
Run Code Online (Sandbox Code Playgroud)
它说他们使用FileDataSourceViaHeapImpl(来自"mp4parser"库)来避免Android上的OOM,所以我决定继续使用它.
事实是,它有4个CTORS,都期望文件有一些变化:File,filePath,FileChannel,FileChannel + fileName. …
android filechannel inputstream android-contentresolver mp4parser
在过去的几年里,我一直在做的视频修剪库的定制,更多更新的版本的工作,在这里(基于这个库)
虽然在大多数情况下,我已经成功地将其定制,甚至将所有文件转换为Kotlin,但它在修剪本身时遇到了一个重大问题.
它假定输入始终是文件,因此如果用户从返回Uri的应用选择器中选择一个项目,它就会崩溃.这样做的原因不仅仅是UI本身,还因为它用于修剪的库(mp4parser)假定只输入File(或文件路径)而不是Uri(在此处写过).我尝试了多种方法来让它获得一个Uri,但失败了.还在这里写了一下.
这就是为什么我使用我在StackOverflow(这里)找到的解决方案进行修剪的原因.关于它的好处是它很安静,只使用Android的框架本身.但是,似乎对于某些视频文件,它总是无法修剪它们.由于这些文件的一个例子,有一个原始库的储存库,在这里(问题报道这里).
看看异常,这就是我得到的:
E: Unsupported mime 'audio/ac3'
E: FATAL EXCEPTION: pool-1-thread-1
Process: life.knowledge4.videocroppersample, PID: 26274
java.lang.IllegalStateException: Failed to add the track to the muxer
at android.media.MediaMuxer.nativeAddTrack(Native Method)
at android.media.MediaMuxer.addTrack(MediaMuxer.java:626)
at life.knowledge4.videotrimmer.utils.TrimVideoUtils.genVideoUsingMuxer(TrimVideoUtils.kt:77)
at life.knowledge4.videotrimmer.utils.TrimVideoUtils.genVideoUsingMp4Parser(TrimVideoUtils.kt:144)
at life.knowledge4.videotrimmer.utils.TrimVideoUtils.startTrim(TrimVideoUtils.kt:47)
at life.knowledge4.videotrimmer.BaseVideoTrimmerView$initiateTrimming$1.execute(BaseVideoTrimmerView.kt:220)
at life.knowledge4.videotrimmer.utils.BackgroundExecutor$Task.run(BackgroundExecutor.java:210)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)
我需要将视频解码为一系列位图,以便我能够修改它们,然后将它们压缩回android中的视频文件.
我计划通过使用getFrameAtTime并将其保存到图像序列来管理它.然后我可以修改序列中的图像并将其编码回电影.但我有两个问题:
getFrameAtTime它用于创建缩略图,并且不保证返回正确的帧.这使视频滞后.我读到使用MediaExtractor进行解码的正确方法,这很好,但我只有示例直接将它呈现给a surfaceView.有什么方法可以将我转换outputBuffer为位图吗?
我需要它来使用16级及以上的api级别.
android ×3
bitmap ×1
filechannel ×1
inputstream ×1
mediacodec ×1
mediamuxer ×1
mp4parser ×1
video ×1