web-dev-qa-db-ja.com

MVIMGの写真/ビデオコンポーネントを抽出する方法

Google Pixel 2とおそらく他のスマートフォンには「モーションフォト」をカバーする機能があります。これらはMVIMGとして保存され、比較的大きいです。

ビデオを削除/抽出する方法を探しています。

これまでのところ、有望なexifタグを見つけました

$ exiftool -xmp:all MVIMG_123.jpg
XMP Toolkit                     : Adobe XMP Core 5.1.0-jc003
Micro Video                     : 1
Micro Video Version             : 1
Micro Video Offset              : 4032524

ビデオは指定されたオフセットに存在する可能性があると思いましたが、これは機能しません:

$ dd if=MVIMG_123.jpg of=video.mp4 bs=4032524 skip=1
$ file video.mp4
video.mp4: data

埋め込みを文書化するリソースはありますか?ビデオを削除/抽出するためのツールさえありますか?

11
rumpel

私は https://github.com/cliveontoast/GoMoPho を見つけました。これはmp4ヘッダーをスキャンしてからビデオをダンプします。

MP4ヘッダーからftypmp4をスキャンして、同じことを実行できます(実際のファイルは4バイト早く開始されます)。

したがって、ビデオを抽出するには:

for i in MVIMG*.jpg; do \
  ofs=$(grep -F --byte-offset --only-matching --text ftypmp4 "$i"); \
  ofs=${ofs%:*}; \
  [[ $ofs ]] && dd "if=$i" "of=${i%.jpg}.mp4" bs=$((ofs-4)) skip=1; \
done

そしてビデオを削除するには:

for i in MVIMG*.jpg; do \
  ofs=$(grep -F --byte-offset --only-matching --text ftypmp4 "$i"); \
  ofs=${ofs%:*}; \
  [[ $ofs ]] && truncate -s $((ofs-4)) "$i"; \
done
6
rumpel

EXIFタグは便利ですが、オフセットはファイルの終わりに関するものです。 mp4ファイルは次の場所に埋め込まれています。

[file_size-micro_video_offset, file_size)

例えば:

$ exiftool -xmp:all MVIMG_123.jpg
XMP Toolkit                     : Adobe XMP Core 5.1.0-jc003
Micro Video                     : 1
Micro Video Version             : 1
Micro Video Offset              : 2107172
Micro Video Presentation Timestamp Us: 966280
$ python -c 'import os; print os.path.getsize("MVIMG_123.jpg") - 2107172'
3322791
$ dd if=MVIMG_123.jpg of=video.mp4 bs=3322791 skip=1
$ file video.mp4 
video.mp4: ISO Media, MP4 v2 [ISO 14496-14]
4
mitchle

grep -F --byte-offset ...が誤ったオフセットを出力するため、/usr/bin/grepddを使用した上記の提案は、macOS High Sierraでは機能しません。 Word ftypmp4、つまり前のLF文字の位置に1を足したものです。間違っていると思うかもしれませんが、とにかく、これが私の解決策です。

for i in MVIMG*.jpg; do \
    Perl -0777 -ne 's/^.*(....ftypmp4.*)$/$1/s && print' "$i" >"${i%.jpg}.mp4"; \
done

これは、Perlの機能を使用して、ファイル全体を一度に丸呑みし、1つの大きな文字列として扱います。先頭に4バイト以上のftypmp4がない場合は、空のファイルが作成されます。複数ある場合は、最後のファイルが抽出されます。

同様に、すべてのファイルからビデオを削除するには:

for i in MVIMG*.jpg; do \
    Perl -0777 -pi -e 's/^(.*?)....ftypmp4.*$/$1/s' "$i"; \
done

これは、Perlのインプレース編集機能を使用します。 ftypmp4が最初に出現した後、先頭の4バイトがすべて切り捨てられます。出現がない場合、ファイルは内容を変更せずに再書き込みされます。

(環境でPERLIO = rawを設定したり、ロケール関連の変数を設定解除したりして、UTF-8解釈を回避する必要がある場合とない場合があります。これは、UTF-8構成ルールに違反するバイトシーケンスを含むバイナリファイルで失敗する可能性があります。 。さまざまなMVIMGファイルを使用したテストでは、そのような問題は発生しませんでした。)

2
Stacko