【发布时间】:2018-04-29 10:25:25
【问题描述】:
我在我的应用程序中使用 FFmpeg 从视频中提取帧,这些帧将被添加到修剪视频视图中,您可以在其中了解视频中特定时间视频中发生的情况。所以每一帧都需要代表视频中的一些时间。
我不太明白 FFmpeg 是如何生成帧的。这是我的代码:
"-i",
videoCroppedFile.getAbsolutePath(),
"-vf",
"fps=1/" + frameSeperation,
mediaStorageDir.getAbsolutePath() +
"/%d.jpg"
我的应用允许您录制最长 20 秒的视频。从视频中提取的帧数取决于捕获的视频的长度。 frameSeparation 是通过以下代码计算得出的。
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long videoLength = Long.parseLong(time) / 1000;
double frameSeperationDouble = (double) videoLength;
// Divide by 11 because there is a maximum of 11 frames on trim video view
frameSeperationDouble /= 11;
frameSeperationDouble = Math.ceil(frameSeperationDouble);
int frameSeperation = (int) frameSeperationDouble;
也许上面的逻辑很糟糕,如果有更好的方法请有人告诉我。
无论如何我运行代码,下面是一些测试用例:
- 拍摄的时长为 6 秒的视频有 7 帧。
- 以 2 秒的长度拍摄的视频有 3 帧。
- 一个长度为 10 秒的视频有 12 帧。
- 拍摄的时长为 15 秒的视频有 9 帧。
- 一个长度为 20 秒的视频有 11 帧。
没有一致性,因此我发现很难为每一帧设置时间戳。我觉得我的逻辑是错误的或者我不理解。非常感谢任何帮助
更新 1
所以我按照你在cmets中说的做了:
final FFmpeg ffmpeg = FFmpeg.getInstance(mContext);
final File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ mContext.getPackageName()
+ "/vFrames");
if (!mediaStorageDir.exists()){
mediaStorageDir.mkdirs();
}
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(mContext, Uri.fromFile(videoCroppedFile));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long videoLength = Long.parseLong(time) / 1000;
double frameSeperationDouble = (double) videoLength / 8;
retriever.release();
final String cmd[] = {
"-i",
videoCroppedFile.getAbsolutePath(),
"-vf",
"fps=1/" + frameSeperationDouble,
"-vframes," + 8,
mediaStorageDir.getAbsolutePath() +
"/%d.jpg"
};
我还在将 vFrames 放入 cmd 的同一点上尝试了 "-vframes=" + 8。它似乎根本不起作用,现在没有从视频中提取帧
【问题讨论】:
-
如果你想获取视频的每一帧,只需去掉
-vf fps=1/[frameseparation]。如果您想每 x 秒捕获一次图像,您可能应该改用-r fps
标签: java android ffmpeg android-ffmpeg