求问各位在安卓开发中对于从相册已获取的视频uri如何进行抽帧处理?
以前采用的retriver类进行处理,但是setDataSource函数的参数永远出错
安卓开发视频抽帧处理
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
3条回答 默认 最新
关注 引自免费微信小程序:皆我百晓生
在Android开发中,如果你想从已有的视频uri中提取帧(即抽帧),你可以使用MediaMetadataRetriever类或者ExifInterface类。这里我会提供一个使用MediaMetadataRetriever的示例。
首先,确保你在build.gradle文件中的
dependencies
部分添加了多媒体相关的库:dependencies { implementation 'com.android.support:multidex:1.0.3' }
然后按照以下步骤操作:
- 创建一个MediaMetadataRetriever实例,并设置数据源。
- 设置你要抓取的帧的时间戳。
- 调用方法extractFrame()获取帧图片。
- 将图片保存到本地或者进行其他处理。
以下是完整的Java代码示例:
import android.content.Context; import android.graphics.Bitmap; import android.media.MediaMetadataRetriever; import android.net.Uri; import java.io.File; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; public class VideoFrameExtractor { public static void extractFramesFromVideo(Context context, Uri videoUri, int frameIntervalInSecs) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(context, videoUri); // 获取视频总时长(单位:毫秒) long durationMs = Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)); int totalFrames = (int) Math.ceil(durationMs / 1000 / frameIntervalInSecs); // 计算总的帧数 for (int i = 0; i < totalFrames; i++) { long timeMs = i * frameIntervalInSecs * 1000; // 计算当前帧的时间戳 Bitmap bitmap = retriever.getFrameAtTime(timeMs, MediaMetadataRetriever.OPTION_CLOSEST); if (bitmap != null) { String fileName = generateFileName(i, "jpg"); saveBitmapToFile(bitmap, context, fileName); System.out.println("Saved frame " + fileName); } } } catch (Exception e) { e.printStackTrace(); } finally { try { retriever.release(); // 释放资源 } catch (Exception ignored) {} } } private static String generateFileName(int index, String extension) { SimpleDateFormat formatter = new SimpleDateFormat("frame_%05d." + extension); return formatter.format(new Date()); } private static boolean saveBitmapToFile(Bitmap bitmap, Context context, String fileName) { File storageDir = getExternalFilesDir(context, "frames"); // 获取外部存储目录 if (storageDir == null) { return false; } File outputFile = new File(storageDir, fileName); try (FileOutputStream out = new FileOutputStream(outputFile)) { bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); return true; } catch (Exception e) { e.printStackTrace(); return false; } } // 在Android 10及以上版本,需要动态请求写入外部存储权限 public static boolean hasWritePermission(Context context) { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } public static void requestWritePermission(Context context) { ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } }
要使用这段代码,你需要在你的Activity或者Fragment中调用
extractFramesFromVideo()
方法:if (!VideoFrameExtractor.hasWritePermission(this)) { VideoFrameExtractor.requestWritePermission(this); } else { VideoFrameExtractor.extractFramesFromVideo(this, uri, 5); // 每5秒抽取一帧 }
其中,
uri
是你要抽取帧的视频uri,5
表示每5秒抽取一帧。如果需要动态请求权限,根据用户的授权情况决定是否调用extractFramesFromVideo()
。注意:这个例子没有处理所有异常情况,实际应用中可能需要对错误进行更详细的处理。另外,如果你的设备运行的是Android 10或更高版本,你还需要处理写入外部存储的权限。
解决 无用评论 打赏 举报 编辑记录
悬赏问题
- ¥15 phython如何实现以下功能?查找同一用户名的消费金额合并—
- ¥15 孟德尔随机化怎样画共定位分析图
- ¥18 模拟电路问题解答有偿速度
- ¥15 CST仿真别人的模型结果仿真结果S参数完全不对
- ¥15 误删注册表文件致win10无法开启
- ¥15 请问在阿里云服务器中怎么利用数据库制作网站
- ¥60 ESP32怎么烧录自启动程序
- ¥50 html2canvas超出滚动条不显示
- ¥15 java业务性能问题求解(sql,业务设计相关)
- ¥15 52810 尾椎c三个a 写蓝牙地址