如何为MediaRecorder API录制的MP4视频添加预览缩略图?
解决MediaRecorder录制的MP4无预览缩略图的问题
嘿,这个问题我之前做视频录制功能时也踩过坑!用MediaRecorder生成的MP4文件没有预览缩略图,确实会给快速识别文件带来麻烦。下面给你几个实用的解决方案,你可以根据自己的场景选择:
方案一:确保录制第一帧为有效画面(最简单的基础优化)
很多系统会自动把视频的第一帧当作缩略图,如果你的视频第一帧是黑屏/空白,就会导致没有预览图。你可以调整录制逻辑,在启动录制前先绘制一帧有效内容到Surface:
// 在调用recorder.start()之前,先绘制第一帧有效Bitmap if (surface != null) { Canvas canvas = surface.lockCanvas(null); canvas.drawBitmap(yourValidBitmap, 0, 0, new Paint()); // yourValidBitmap是你想作为缩略图的画面 surface.unlockCanvasAndPost(canvas); } // 再启动录制 recorder.start();
这个方法简单,但依赖系统媒体库的识别逻辑,部分设备可能不生效。
方案二:录制完成后嵌入缩略图(可靠通用方案)
如果方案一不管用,我们可以手动给MP4文件添加缩略图,分两种实现思路:
方法A:更新系统媒体库的缩略图记录
这个方法是给系统媒体库添加缩略图关联,不需要修改MP4文件本身,适合大多数日常场景:
// 录制完成后调用此方法 private void updateVideoThumbnail(String videoPath) { MediaMetadataRetriever retriever = new MediaMetadataRetriever(); try { retriever.setDataSource(videoPath); // 提取视频第1秒处的帧作为缩略图(单位是微秒) Bitmap thumbnail = retriever.getFrameAtTime(1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); // 更新媒体库,让系统识别到这张缩略图 ContentValues values = new ContentValues(); values.put(MediaStore.Video.Media.THUMBNAIL, bitmapToBytes(thumbnail)); ContentResolver resolver = getContentResolver(); Uri videoUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; String whereClause = MediaStore.Video.Media.DATA + "=?"; resolver.update(videoUri, values, whereClause, new String[]{videoPath}); thumbnail.recycle(); } catch (Exception e) { e.printStackTrace(); } finally { retriever.release(); } } // 将Bitmap转为字节数组的工具方法 private byte[] bitmapToBytes(Bitmap bitmap) { ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); return stream.toByteArray(); }
注意:这个方法的效果取决于文件管理器是否读取系统媒体库的数据,部分第三方文件管理器可能不生效。
方法B:直接修改MP4文件嵌入缩略图(最彻底的方案)
如果需要让缩略图直接嵌入MP4文件本身(任何设备/软件打开都能看到),可以用轻量第三方库MP4Parser实现:
首先添加依赖:
implementation "com.googlecode.mp4parser:isoparser:1.1.22"
然后编写代码嵌入外部图片或视频帧作为缩略图:
import com.googlecode.mp4parser.authoring.Movie; import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator; import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder; import java.io.File; import java.io.FileOutputStream; import java.nio.channels.FileChannel; import java.io.IOException; // 嵌入外部图片作为MP4缩略图 private void embedThumbnailToMp4(String videoPath, String thumbnailImgPath) throws IOException { Movie movie = MovieCreator.build(videoPath); // 找到视频轨道并设置缩略图 for (com.googlecode.mp4parser.authoring.Track track : movie.getTracks()) { if ("vide".equals(track.getHandler())) { // 读取外部图片并转为字节数组 Bitmap thumbnail = BitmapFactory.decodeFile(thumbnailImgPath); ByteArrayOutputStream baos = new ByteArrayOutputStream(); thumbnail.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] thumbnailBytes = baos.toByteArray(); track.getTrackMetaData().setPicture(thumbnailBytes); thumbnail.recycle(); break; } } // 重新生成带缩略图的MP4文件 File outputFile = new File(videoPath.replace(".mp4", "_with_thumb.mp4")); FileChannel fc = new FileOutputStream(outputFile).getChannel(); new DefaultMp4Builder().build(movie).writeContainer(fc); fc.close(); }
这个方法会直接修改MP4的元数据,兼容性拉满,所有支持MP4缩略图的工具都能识别。
方案三:录制时同步保存独立缩略图文件(最直接的备用方案)
如果上面的方法都觉得繁琐,你可以在开始录制时,同时把目标Bitmap保存为一张单独的图片,和视频放在同一目录下,命名保持对应(比如视频名video_2310121530.mp4,缩略图video_2310121530_thumb.jpg)。虽然不是嵌入到视频里,但用户浏览文件时能快速对应识别,简单有效。
内容的提问来源于stack exchange,提问作者mozer
相关产品推荐
相关产品推荐

