如何批量修改MP4视频文件的时间戳元数据

3
最近我发现我的一个相机的内部时钟比实际时间晚了近两年,导致我的照片和视频在库中的时间顺序混乱。我很快发现exiftool的批量更新功能非常棒,date/time shift feature。不幸的是,它还不支持修改MP4视频文件。
$ exiftool -AllDates+="0:0:729 3:17:0" test.mp4
Error: Writing of MP4 files is not yet supported - test.mp4
    0 image files updated
    1 files weren't updated due to errors

我该如何为MP4视频文件执行类似的批量日期移动功能?
2个回答

1

基于QuickTime文件格式规范,我编写了一个Python脚本的概念证明,用于粗略地移动时间戳,以便暂时解决问题:

#!/usr/bin/env python
import datetime
import sys

def int_bytes(raw):
    value = 0
    for byte in raw:
        value <<= 8
        value += ord(byte)
    return value

def bytes_int(value, size=4):
    raw = []
    for byte in range(size):
        raw.append(chr((value >> 8*byte) % 256))
    return ''.join(reversed(raw))


ATOM_FORMAT = (
    ('atom_size', 4, int_bytes),
    ('type', 4, str),
    ('version', 1, int_bytes),
    ('flags', 3, int_bytes),
    ('creation_time', 4, int_bytes),
    ('modification_time', 4, int_bytes),
    # that's all I need for now, and is common
    # between tkhd, mvhd and mdhd
    # ...
)

ATOM_TYPES = ('tkhd', 'mvhd', 'mdhd')

TIMESTAMP_EPOCH = datetime.datetime(1904, 1, 1, 0, 0)

def from_timestamp(timestamp):
    return TIMESTAMP_EPOCH + datetime.timedelta(0, timestamp)

def to_timestamp(datetime_obj):
    return int((datetime_obj - TIMESTAMP_EPOCH).total_seconds())

def shift_dates(mp4, atom_type, delta):
    # TODO: refactor
    mp4.seek(0)
    data = mp4.read() # TODO: don't load whole file
    type_index = -1
    while True:
        try:
            type_index = data.index(atom_type, type_index+1)
        except ValueError:
            if type_index < 0:
                raise RuntimeError('Cannot find atom: {}'.format(atom_type))
            else:
                break
        else:
            sys.stdout.write(
                '  Found {} at {}\n'.format(atom_type, type_index))
        offset = type_index - ATOM_FORMAT[0][1]

        header_data = {}
        offsets = {}
        for field, size, convert in ATOM_FORMAT:
            offsets[field] = offset
            offset += size
            header_data[field] = convert(data[offsets[field]:][:size])

        for field in ('creation_time', 'modification_time'):
            original = from_timestamp(header_data[field])
            shifted = original + delta
            mp4.seek(offsets[field])
            mp4.write(bytes_int(to_timestamp(shifted)))
            sys.stdout.write(
                '    {}: {} -> {}\n'.format(field, original, shifted))


if __name__ == '__main__':
    try:
        filename = sys.argv[1]
        days, seconds = map(int, sys.argv[2:])
    except (IndexError, TypeError, ValueError):
        sys.stderr.write(
            "USAGE: {} mp4_file days seconds\n".format(
                sys.argv[0]
            )
        )
        sys.exit(1)

    try:
        f = open(filename, 'rwb+')
    except IOError:
        sys.stderr.write("ERROR: cannot open {}\n".format(filename))
        sys.exit(1)
    else:
        delta = datetime.timedelta(days, seconds)
        sys.stdout.write(
            'Shifting timestamps of {} by {!r}:\n'.format(filename, delta))
        for atom_type in ATOM_TYPES:
            shift_dates(f, atom_type, delta)
        f.close()
        sys.stdout.write('Done.\n')

0

ExifTool现在可以编辑MP4/MOV视频文件中的时间戳和许多其他标签。但是,由于AllDates标签仅编辑三个特定的标签,其中两个在视频文件中很少出现,因此上述命令只会编辑视频文件中的一个标签(有关AllDates的说明,请参见快捷标记名称页面)。

要编辑所有与时间相关的标签,可以使用以下命令:
exiftool -Time:All+="0:0:729 3:17:0" test.mp4


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接