web-dev-qa-db-fra.com

Comment extraire le composant Photo / Vidéo d'un MVIMG?

Le Google Pixel 2 et probablement d'autres téléphones ont depuis la capacité de couvrir "Motion Photos". Celles-ci sont enregistrées en tant que MVIMG et relativement grandes.

Je cherche un moyen de supprimer/extraire la vidéo.

Jusqu'à présent, j'ai trouvé une balise exif prometteuse

$ 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

Je pensais que la vidéo pouvait être présente avec le décalage spécifié, mais cela ne fonctionne pas:

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

Existe-t-il des ressources qui documentent l'intégration? Existe-t-il même des outils pour supprimer/extraire la vidéo?

11
rumpel

J'ai trouvé https://github.com/cliveontoast/GoMoPho qui recherche l'en-tête mp4 puis vide la vidéo.

Nous pouvons faire de même, en recherchant ftypmp4 à partir de l'en-tête MP4 (le fichier réel commence 4 octets plus tôt):

Ainsi pour extraire des vidéos:

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

Et pour supprimer des vidéos:

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

La balise EXIF ​​est utile, mais le décalage se fait par rapport à la fin du fichier. Le fichier mp4 est intégré à:

[file_size-micro_video_offset, file_size)

Par exemple:

$ 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

La suggestion ci-dessus utilisant grep -F --byte-offset ... et dd ne fonctionne pas pour moi sur macOS High Sierra comme /usr/bin/grep affiche un mauvais décalage - je suppose que cela donne le décalage de la "ligne" qui contient le mot ftypmp4, c'est-à-dire la position du précédent LF caractère plus un. Je suppose que c'est faux, mais de toute façon, c'est ma solution:

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

Cela utilise la capacité de Perl à Slurp dans un fichier entier à la fois et à le traiter comme une grande chaîne. Sinon ftypmp4 avec au moins quatre octets de tête est présent, un fichier vide est créé, si plusieurs sont présents, le dernier est extrait.

De même, pour supprimer la vidéo de tous les fichiers:

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

Cela utilise la fonction d'édition sur place de Perl. Tout après la première occurrence de ftypmp4 avec ses quatre octets de tête est coupé. S'il n'y a aucune occurrence, le fichier est réécrit avec son contenu inchangé.

(Il peut être nécessaire ou non de définir PERLIO = raw dans l'environnement et/ou de désactiver les variables liées aux paramètres régionaux pour éviter une interprétation UTF-8, qui pourrait échouer pour les fichiers binaires qui contiennent des séquences d'octets qui violent les règles de composition UTF-8 Lors de mes tests avec divers fichiers MVIMG, aucun problème de ce type ne s'est produit.)

2
Stacko