You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Android上修改视频创建/修改日期?Mp4Composer裁剪后保留原日期

Android修改视频创建/修改日期 & Mp4Composer裁剪保留原元数据方案

一、Android端通用修改视频日期的方法

不管是要修改视频的创建日期还是修改日期,可以根据你的Android版本选择下面两种靠谱的方式:

1. API 29+(Android 10及以上):用MediaStore更新

Android 10开始限制直接操作文件,推荐用系统的MediaStore来修改媒体元数据,兼容性拉满:

fun updateVideoDate(context: Context, videoUri: Uri, targetDate: Long) {
    val values = ContentValues().apply {
        put(MediaStore.Video.Media.DATE_ADDED, targetDate / 1000) // 秒级时间戳
        put(MediaStore.Video.Media.DATE_MODIFIED, targetDate / 1000)
        put(MediaStore.Video.Media.DATE_TAKEN, targetDate) // 拍摄日期,毫秒级
    }
    context.contentResolver.update(videoUri, values, null, null)
}

调用时传入原视频的Uri和你想要设置的日期时间戳就行。

2. API 28及以下:直接修改文件属性

低版本可以直接操作File对象的属性,简单直接:

fun updateVideoFileDate(videoFile: File, targetDate: Long) {
    // 修改文件的最后修改时间(对应系统显示的修改日期)
    videoFile.setLastModified(targetDate)
    // 如果要修改视频内部的拍摄元数据,可搭配MediaMetadataRetriever读取后再写入,或者用ExifInterface处理
    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(videoFile.path)
    // 这里可以读取原拍摄日期,修改后写回,注意视频的Exif兼容性
}

二、Mp4Composer裁剪后保留原视频日期的解决办法

我之前用Mp4Composer做裁剪时也踩过这个坑——输出视频的元数据日期默认是当前时间,查了官方API确实没有直接在编码阶段设置日期的接口,所以用「先存原日期,裁剪完成后再修改」的思路完美解决:

步骤1:获取原视频的日期元数据

先用MediaMetadataRetriever拿到原视频的拍摄/创建日期,优先取拍摄元数据,没有的话 fallback 到文件修改时间:

fun getOriginalVideoDate(videoPath: String): Long? {
    val retriever = MediaMetadataRetriever()
    return try {
        retriever.setDataSource(videoPath)
        // 先尝试拿拍摄日期
        val dateTakenStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE_TAKEN)
        dateTakenStr?.toLong() ?: run {
            // 没有拍摄日期就拿文件修改时间
            File(videoPath).lastModified()
        }
    } catch (e: Exception) {
        e.printStackTrace()
        null
    } finally {
        retriever.release()
    }
}

步骤2:裁剪完成后同步原日期

按你原来的逻辑完成裁剪,在onCompleted回调里修改输出文件的日期:

Mp4Composer(sourcePath, outputPath)
    .trim(startTimeMs, endTimeMs)
    .listener(object : Mp4Composer.Listener {
        override fun onCompleted() {
            // 拿到原视频的日期
            val originalDate = getOriginalVideoDate(sourcePath)
            originalDate?.let {
                // 根据系统版本选择修改方式
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    // 先获取输出文件的ContentUri,再用MediaStore修改
                    val outputUri = getContentUriFromPath(context, outputPath)
                    outputUri?.let { uri -> updateVideoDate(context, uri, it) }
                } else {
                    updateVideoFileDate(File(outputPath), it)
                }
            }
        }
        override fun onProgress(progress: Double) {}
        override fun onFailed(exception: Exception) {}
    })
    .start()

进阶:修改MP4内部元数据(比如moov里的creation_time)

如果需要让MP4文件本身的内部元数据(比如ISO BMFF标准里的creation_time字段)也同步原日期,就用mp4parser库来修改:

// Java示例,Kotlin可直接转译
File inputFile = new File(outputPath);
File outputFile = new File(outputPath + "_temp.mp4");
IsoFile isoFile = new IsoFile(inputFile.getAbsolutePath());
Movie movie = new Movie();
for (TrackBox trackBox : isoFile.getMovieBox().getBoxes(TrackBox.class)) {
    movie.addTrack(new Mp4TrackImpl(trackBox));
}
// 设置创建时间和修改时间为原视频日期
movie.setCreationTime(originalDate);
movie.setModificationTime(originalDate);
// 重新生成MP4文件
Container container = new DefaultMp4Builder().build(movie);
FileOutputStream fos = new FileOutputStream(outputFile);
FileChannel fc = fos.getChannel();
container.writeContainer(fc);
fc.close();
fos.close();
// 替换原输出文件
inputFile.delete();
outputFile.renameTo(inputFile);

这个方法能直接修改MP4文件的底层元数据,确保不管用什么播放器查看,日期都是原视频的。


内容的提问来源于stack exchange,提问作者Adam Styrc

火山引擎 最新活动