miniDVテープをデジタル化するときに日付データがなくてGoogle Photoなどのサービスにアップすると大昔のデータなのに2025年と表示されてしまい、困ったのでツールを作りました。(とは言っても半分くらいAIが作ってくれました)
ダビングの仕方
これは以前書いたのでこちらをご覧ください。
戦略
mediainfoで見ると以下のようになっています。
Format : AVI Format/Info : Audio Video Interleave Commercial name : DVCPRO Format settings : BitmapInfoHeader / WaveFormatEx File size : 1.34 GiB Duration : 6 min 25 s Overall bit rate mode : Constant Overall bit rate : 29.8 Mb/s Frame rate : 29.970 FPS Recorded date : 2001-05-01 11:07:52.000 Video ID : 0 Format : DV Commercial name : DVCPRO Codec ID : dvsd Codec ID/Hint : Sony Duration : 6 min 25 s Bit rate mode : Constant Bit rate : 24.4 Mb/s Width : 720 pixels Height : 480 pixels Display aspect ratio : 4:3 Frame rate mode : Constant Frame rate : 29.970 (30000/1001) FPS Original frame rate : 29.970 (29970/1000) FPS Standard : NTSC Color space : YUV Chroma subsampling : 4:1:1 Bit depth : 8 bits Scan type : Interlaced Scan order : Bottom Field First Compression mode : Lossy Bits/(Pixel*Frame) : 2.357 Time code of first frame : 00:58:39;07 Time code source : Subcode time code Stream size : 1.29 GiB (97%) Encoding settings : ae mode=full automatic / wb mode=automatic / white balance= / fcm=manual focus Audio ID : 1 Format : PCM Format settings : Little / Signed Codec ID : 1 Duration : 6 min 25 s Bit rate mode : Constant Bit rate : 1 024 kb/s Channel(s) : 2 channels Sampling rate : 32.0 kHz Bit depth : 16 bits Stream size : 47.1 MiB (3%) Alignment : Aligned on interleaves Interleave, duration : 33 ms (1.00 video frame)
DV形式、DVCPROというもののようです。 Recoded Dateというのがありますね!これがなかったら詰んでましたがあったので助かりました。これを使ってサービスが撮影日時を認識できるようにします。詳しいコンテナの実装はこの辺にありそうです。
手順としては以下です。
- AVI動画
- ファイル名を日時に変更するrename.pyを実行(必要な人向け)
- AVI動画を任意のツールで圧縮エンコード
- mp4のexifに撮影日時として書き込むserch_and_setExif.py を実行
AVIコンテナはEXIFが存在しないので現代的なmp4コンテナに収めるときにどうしよう問題があります。なので、一度AVI→日付付きAVI→mp4エンコード→EXIF付きmp4としました。
なお、一度日付付きAVIとしてる理由はわかりやすいからです。別に、AVI→mp4エンコード→EXIF書き込みとしても問題ないです。一応AVIファイルもアーカイブ用のHDDに保存しておきたかったのでこうしてます。
注意
大事な動画データですので、スクリプトを実行する前に動作に問題がないか、確かめてから本番を実行してください。必ず、先にコピーしてテストディレクトリで実行してください。
筆者はいかなる損失に対しても責任を負いません。
動作確認済みの環境
- MacOS LinuxももちろんOKです。Windowsは...WSLを使うのが最も簡単な手段かもしれないです。PS版も需要があれば作ります。 subprocessなので、パスだけ直せばWindowsでも動くはずです...動作は未確認。
- Python 3.10.12 なんでも動くと思います。
- exiftool
- mediainfo
ファイル名を日時に変更する
mediainfoをインストールしてください。コマンドから使うのでCLI版が必要です。デスクチップ版も便利なので入れて損ないです。
使い方
python rename.py "/path/to/your/video"/dir
ディレクトリを動画が置いてあるところにしてください。今回は同じディレクトリに置いてます。
-rwx------@ 1 fumi staff 369060664 1 2 16:55 2001-05-01-103426.avi -rwx------@ 1 fumi staff 218615516 1 2 16:55 2001-05-01-103656.avi -rwx------@ 1 fumi staff 439185504 1 2 16:55 2001-05-01-104506.avi -rwx------@ 1 fumi staff 1438340196 1 2 16:55 2001-05-01-110752.avi -rwx------@ 1 fumi staff 348545416 1 2 16:55 2001-05-01-112422.avi -rw-r--r--@ 1 fumi staff 1675 1 4 00:44 rename.py -rw-r--r--@ 1 fumi staff 2393 1 3 02:08 serch_and_setExif.py
ちゃんと日時がaviファイルに入ってれば同一ディレクトリのaviファイルを探してmediainfoのrecoded dateにファイル名を変更してくれます。
> python rename.py /your/path/ ✔ at 00:28:19 Renamed: 20250102200831.avi -> 2000-05-11-081019.avi Renamed: 20250103201621.avi -> 1998-12-10-112504.avi Renamed: 20250102215541.avi -> 1999-09-06-172403.avi Renamed: 20250103142213.avi -> 1999-05-05-184932.avi Renamed: 20250102233753.avi -> 1999-03-11-215045.avi Renamed: 20250102182444.avi -> 1999-08-15-142603.avi Renamed: 20250102175027.avi -> 1999-08-17-210528.avi Renamed: 20250102155526.avi -> 2001-02-12-171835.avi Renamed: 20250102183606.avi -> 1999-08-15-145835.avi Renamed: 20250102163902.avi -> 2001-05-01-103656.avi Renamed: 20250103130054.avi -> 1999-04-30-153925.avi
mp4のexifに撮影日時として書き込む
serch_and_setExif.pyを使って同一ファイル名のAVI動画とmp4動画を探して、mediainfoで抽出したrecoded dateをexiftoolを使って書き込みます。mp4コンテナであればいいのでavc(h.264)でもheif(h.265)でも構いません。 Exiftoolが入ってる必要があります。ここから入れてください。 exiftool.org
python serch_and_setExif.py "/path/to/your/video"
これのディレクトリを動画が置いてあるところにしてください。今回は同じディレクトリに置いてます。
実行できるとこのようになります。
> python serch_and_setExif.py 1 image files updated Metadata written to ./1998-12-31-152525.mp4 1 image files updated Metadata written to ./1998-12-31-171935.mp4 1 image files updated Metadata written to ./1998-12-30-215320.mp4 1 image files updated Metadata written to ./1998-12-30-194932.mp4
確認するとちゃんとCreateDateなどが修正されてると思います。認識されるか、GooglePhotosに突っ込んで確認してみてください。
exiftool -j './avi_files/test/1998-12-30-194932.mp4' [{ "SourceFile": "./avi_files/test/1998-12-30-194932.mp4", "ExifToolVersion": 13.11, "FileName": "1998-12-30-194932.mp4", "Directory": "./avi_files/test", "FileSize": "232 MB", "FileModifyDate": "2025:01:04 00:52:43+09:00", "FileAccessDate": "2025:01:04 00:52:43+09:00", "FileInodeChangeDate": "2025:01:04 00:52:43+09:00", "FilePermissions": "-rw-r--r--", "FileType": "MP4", "FileTypeExtension": "mp4", "MIMEType": "video/mp4", "MajorBrand": "MP4 v2 [ISO 14496-14]", "MinorVersion": "0.0.0", "CompatibleBrands": ["mp42","mp41"], "MovieHeaderVersion": 0, "TimeScale": 90000, "Duration": "0:03:01", "PreferredRate": 1, "PreferredVolume": "100.00%", "PreviewTime": "0 s", "PreviewDuration": "0 s", "PosterTime": "0 s", "SelectionTime": "0 s", "SelectionDuration": "0 s", "CurrentTime": "0 s", "NextTrackID": 3, "TrackHeaderVersion": 0, "TrackCreateDate": "2025:01:02 16:28:01", "TrackModifyDate": "2025:01:02 16:28:01", "TrackID": 2, "TrackDuration": "0:03:01", "TrackLayer": 0, "TrackVolume": "100.00%", "Balance": 0, "AudioFormat": "mp4a", "AudioChannels": 2, "AudioBitsPerSample": 16, "MatrixStructure": "1 0 0 0 1 0 0 0 1", "ImageWidth": 654, "ImageHeight": 480, "MediaHeaderVersion": 0, "MediaCreateDate": "1998:12:30 10:49:32", "MediaModifyDate": "1998:12:30 10:49:32", "MediaTimeScale": 30000, "MediaDuration": "0:03:01", "MediaLanguageCode": "eng", "GraphicsMode": "srcCopy", "OpColor": "0 0 0", "HandlerType": "Alias Data", "HandlerDescription": "Alias Data Handler", "CompressorID": "avc1", "SourceImageWidth": 720, "SourceImageHeight": 480, "XResolution": 72, "YResolution": 72, "CompressorName": "AVC Coding", "BitDepth": 24, "StartTimecode": "00;01;29;04", "XMPToolkit": "Image::ExifTool 13.11", "Format": "H.264", "Orientation": "Horizontal (normal)", "CreateDate": "1998:12:30 10:49:32", "MetadataDate": "2025:01:03 01:28:26+09:00", "ModifyDate": "1998:12:30 10:49:32", ---省略 }
動画が存在しないと以下のようになります。
> python serch_and_setExif.py "your/path/" ✔ took 12s at 00:28:36 MP4 file not found for ./1999-08-09-095536.avi MP4 file not found for ./1999-03-14-105041.avi MP4 file not found for ./1999-03-20-220908.avi
(余談)エンコード
今回はAdobe Media Encoderを使ってAVI(DVCPRO)をmp4(h.265)にVBR 8Mbpsでエンコードしました。ファイルサイズは大体1/2—1/6くらいになってるようです。解像度も低いのでもっと絞れると思いますが、意外とブロックノイズが見えるのでこれくらいにしておきました。
Adobe使ってない人はXmediaEncoderとかでいけると思います。
-rw-r--r--@ 1 fumi staff 56584759 1 3 17:40 2003-09-23-113903.mp4 -rwx------@ 1 fumi staff 1299582516 12 31 15:24 2003-09-23-114153.avi -rw-r--r--@ 1 fumi staff 332879571 1 3 17:41 2003-09-23-114153.mp4 -rwx------@ 1 fumi staff 188029152 12 31 15:24 2003-09-23-120615.avi -rw-r--r--@ 1 fumi staff 45623023 1 3 17:40 2003-09-23-120615.mp4 -rwx------@ 1 fumi staff 476610280 12 31 15:24 2003-09-23-125425.avi -rw-r--r--@ 1 fumi staff 120132999 1 3 17:40 2003-09-23-125425.mp4 -rwx------@ 1 fumi staff 2560532688 12 31 15:24 2003-09-23-131705.avi -rw-r--r--@ 1 fumi staff 657000369 1 3 17:41 2003-09-23-131705.mp4 -rw-r--r--@ 1 fumi staff 1684 1 3 00:31 rename.py -rw-r--r--@ 1 fumi staff 2393 1 3 02:08 serch_and_setExif.py
ffmpegでカッコよく実行したかったのですがAVIファイルが破損してるとのエラーが出てしまい、諦めました。修復オプションや保存し直しも試したのですがダメでした。残念。
ffmpeg -i 2002-11-29-112655.avi -c:v hevc_videotoolbox -b:v 6M output.mp4 -codec copy ffmpeg version 7.1 Copyright (c) 2000-2024 the FFmpeg developers built with Apple clang version 16.0.0 (clang-1600.0.26.4) configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.1_3 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon libavutil 59. 39.100 / 59. 39.100 libavcodec 61. 19.100 / 61. 19.100 libavformat 61. 7.100 / 61. 7.100 libavdevice 61. 3.100 / 61. 3.100 libavfilter 10. 4.100 / 10. 4.100 libswscale 8. 3.100 / 8. 3.100 libswresample 5. 3.100 / 5. 3.100 libpostproc 58. 3.100 / 58. 3.100 Trailing option(s) found in the command: may be ignored. [avi @ 0x12b62c6f0] ODML index invalid Last message repeated 1 times [aist#0:1/pcm_s16le @ 0x12b62d480] Guessed Channel Layout: stereo Input #0, avi, from '2002-11-29-112655.avi': Duration: 00:18:53.73, start: 0.000000, bitrate: 29799 kb/s Stream #0:0: Video: dvvideo (dvsd / 0x64737664), yuv411p, 720x480 [SAR 8:9 DAR 4:3], 28771 kb/s, 29.97 fps, 29.97 tbr, 29.97 tbn Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 32000 Hz, stereo, s16, 1024 kb/s File 'output.mp4' already exists. Overwrite? [y/N] y Stream mapping: Stream #0:0 -> #0:0 (dvvideo (native) -> hevc (hevc_videotoolbox)) Stream #0:1 -> #0:1 (pcm_s16le (native) -> aac (native)) Press [q] to stop, [?] for help Output #0, mp4, to 'output.mp4': Metadata: encoder : Lavf61.7.100 Stream #0:0: Video: hevc (hev1 / 0x31766568), yuv420p(tv, bottom coded first (swapped)), 720x480 [SAR 8:9 DAR 4:3], q=2-31, 6000 kb/s, 29.97 fps, 30k tbn Metadata: encoder : Lavc61.19.100 hevc_videotoolbox Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 32000 Hz, stereo, fltp, 128 kb/s Metadata: encoder : Lavc61.19.100 aac [dvvideo @ 0x12b632cc0] Concealing bitstream errors:00:07.60 bitrate=6064.7kbits/s speed=15.2x Last message repeated 20 times [dvvideo @ 0x12b633290] Concealing bitstream errors Last message repeated 14 times [dvvideo @ 0x12b633860] Concealing bitstream errors:01:09.66 bitrate=6140.7kbits/s speed=23.1x Last message repeated 12 times [dvvideo @ 0x12b634400] Concealing bitstream errors:02:36.32 bitrate=6144.3kbits/s speed=23.9x Last message repeated 34 times [dvvideo @ 0x12b633e30] Concealing bitstream errors:04:15.62 bitrate=6144.9kbits/s speed=24.2x Last message repeated 11 times [dvvideo @ 0x12b633e30] Concealing bitstream errors:06:32.22 bitrate=6138.1kbits/s speed=24.3x Last message repeated 10 times [dvvideo @ 0x12b6326f0] Concealing bitstream errors:14:06.87 bitrate=6141.3kbits/s speed=24.3x Last message repeated 14 times [dvvideo @ 0x12b634400] Concealing bitstream errors Last message repeated 134 times [out#0/mp4 @ 0x12b62d6a0] video:832133KiB audio:17634KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.068265% frame=33978 fps=730 q=-0.0 Lsize= 850347KiB time=00:18:45.66 bitrate=6188.4kbits/s speed=24.2x [aac @ 0x12b635a40] Qavg: 757.993
ffmpeg -i 2002-11-29-112655.avi -c:v hevc_videotoolbox -b:v 6M output.mp4 -codec copy ffmpeg version 7.1 Copyright (c) 2000-2024 the FFmpeg developers built with Apple clang version 16.0.0 (clang-1600.0.26.4) configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.1_3 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon libavutil 59. 39.100 / 59. 39.100 libavcodec 61. 19.100 / 61. 19.100 libavformat 61. 7.100 / 61. 7.100 libavdevice 61. 3.100 / 61. 3.100 libavfilter 10. 4.100 / 10. 4.100 libswscale 8. 3.100 / 8. 3.100 libswresample 5. 3.100 / 5. 3.100 libpostproc 58. 3.100 / 58. 3.100 Trailing option(s) found in the command: may be ignored. [avi @ 0x12b62c6f0] ODML index invalid Last message repeated 1 times [aist#0:1/pcm_s16le @ 0x12b62d480] Guessed Channel Layout: stereo Input #0, avi, from '2002-11-29-112655.avi': Duration: 00:18:53.73, start: 0.000000, bitrate: 29799 kb/s Stream #0:0: Video: dvvideo (dvsd / 0x64737664), yuv411p, 720x480 [SAR 8:9 DAR 4:3], 28771 kb/s, 29.97 fps, 29.97 tbr, 29.97 tbn Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 32000 Hz, stereo, s16, 1024 kb/s File 'output.mp4' already exists. Overwrite? [y/N] y Stream mapping: Stream #0:0 -> #0:0 (dvvideo (native) -> hevc (hevc_videotoolbox)) Stream #0:1 -> #0:1 (pcm_s16le (native) -> aac (native)) Press [q] to stop, [?] for help Output #0, mp4, to 'output.mp4': Metadata: encoder : Lavf61.7.100 Stream #0:0: Video: hevc (hev1 / 0x31766568), yuv420p(tv, bottom coded first (swapped)), 720x480 [SAR 8:9 DAR 4:3], q=2-31, 6000 kb/s, 29.97 fps, 30k tbn Metadata: encoder : Lavc61.19.100 hevc_videotoolbox Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 32000 Hz, stereo, fltp, 128 kb/s Metadata: encoder : Lavc61.19.100 aac [dvvideo @ 0x12b632cc0] Concealing bitstream errors:00:07.60 bitrate=6064.7kbits/s speed=15.2x Last message repeated 20 times [dvvideo @ 0x12b633290] Concealing bitstream errors Last message repeated 14 times [dvvideo @ 0x12b633860] Concealing bitstream errors:01:09.66 bitrate=6140.7kbits/s speed=23.1x Last message repeated 12 times [dvvideo @ 0x12b634400] Concealing bitstream errors:02:36.32 bitrate=6144.3kbits/s speed=23.9x Last message repeated 34 times [dvvideo @ 0x12b633e30] Concealing bitstream errors:04:15.62 bitrate=6144.9kbits/s speed=24.2x Last message repeated 11 times [dvvideo @ 0x12b633e30] Concealing bitstream errors:06:32.22 bitrate=6138.1kbits/s speed=24.3x Last message repeated 10 times [dvvideo @ 0x12b6326f0] Concealing bitstream errors:14:06.87 bitrate=6141.3kbits/s speed=24.3x Last message repeated 14 times [dvvideo @ 0x12b634400] Concealing bitstream errors Last message repeated 134 times [out#0/mp4 @ 0x12b62d6a0] video:832133KiB audio:17634KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.068265% frame=33978 fps=730 q=-0.0 Lsize= 850347KiB time=00:18:45.66 bitrate=6188.4kbits/s speed=24.2x [aac @ 0x12b635a40] Qavg: 757.993
なぜかWindowsのMedia Encoderだけうまくいきました。MacのMedia encoderはそもそも非対応っぽいです。OS標準のエンコーダもありますが、非対応でした。
avconvert: invalid configuration (preset name Preset640x480) with file:///Users/fumi/2001-04-15-113339.avi Presets compatible with file:///Users/fumi/2001-04-15-113339.avi: Preset640x480 Preset960x540 Preset1280x720 Preset1920x1080 Preset3840x2160 PresetAppleM4A PresetAppleM4V480pSD PresetAppleM4V720pHD PresetAppleM4V1080pHD PresetAppleM4VAppleTV PresetAppleM4VCellular PresetAppleM4ViPod PresetAppleM4VWiFi PresetAppleProRes422LPCM PresetAppleProRes4444LPCM PresetHEVC1920x1080 PresetHEVC3840x2160 PresetHEVC7680x4320 PresetHEVCHighestQuality PresetHighestQuality PresetLowQuality PresetMediumQuality