代码之家  ›  专栏  ›  技术社区  ›  rumpel

如何提取MVIMG的照片/视频组件?

  •  1
  • rumpel  · 技术社区  · 7 年前

    谷歌Pixel2和其他手机可能已经具备了覆盖“动态照片”的功能。它们被保存为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
    

    3 回复  |  直到 7 年前
        1
  •  13
  •   rumpel    7 年前

    我确实找到了 https://github.com/cliveontoast/GoMoPho

    我们也可以这样做,扫描 ftypmp4

    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
    
        2
  •  6
  •   mitchle    7 年前

    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]
    
        3
  •  4
  •   Jerry Peek    6 年前

    #!/bin/bash
    # extract-mvimg: Extract .mp4 video and .jpg still image from a Pixel phone
    # camera "motion video" file with a name like MVIMG_20191216_153039.jpg
    # to make files like IMG_20191216_153039.jpg and IMG_20191216_153039.mp4
    #
    # Usage: extract-mvimg MVIMG*.jpg [MVIMG*.jpg...]
    
    for srcfile
    do
      case "$srcfile" in
      MVIMG_*_*.jpg) ;;
      *)
        echo "extract-mvimg: skipping '$srcfile': not an MVIMG*.jpg file?" 2>&1
        continue
        ;;
      esac
    
      # Get base filename: strip leading MV and trailing .jpg
      # Example: MVIMG_20191216_153039.jpg becomes IMG_20191216_153039
      basefile=${srcfile#MV}
      basefile=${basefile%.jpg}
    
      # Get byte offset. Example output: 2983617:ftypmp4
      offset=$(grep -F --byte-offset --only-matching --text ftypmp4 "$srcfile")
      # Strip trailing text. Example output: 2983617
      offset=${offset%:*}
    
      # If $offset isn't an empty string, create .mp4 file and
      # truncate a copy of input file to make .jpg file.
      if [[ $offset ]]
      then
        dd status=none "if=$srcfile" "of=${basefile}.mp4" bs=$((offset-4)) skip=1
        cp -ip "$srcfile" "${basefile}.jpg" || exit 1
        truncate -s $((offset-4)) "${basefile}.jpg"
      else
        echo "extract-mvimg: can't find ftypmp4 in $srcfile; skipping..." 2>&1
      fi
    done
    

    status=none禁止dd输出的“1+1 records in”和“1+1 records out”状态。如果您的dd不理解,您可以将其删除。

        4
  •  3
  •   Stacko    7 年前

    以上建议使用 grep -F --byte-offset ... 和 dd /usr/bin/grep 输出一个错误的偏移量我猜它会产生包含单词的“行”的偏移量 ftypmp4 ,即前一个LF字符的位置加一。我可能猜错了,但不管怎样,这是我的解决方案:

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

    这使用了 perl 一次把一个文件弄成一个大字符串。如果没有 ftypmp4型

    同样,要从所有文件中删除视频:

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

    这将使用的在位编辑功能 . 在第一次发生 它的四个前导字节被切断。如果没有出现,则重写文件时其内容保持不变。

    (可能需要也可能不需要在环境中设置PERLIO=raw和/或取消设置与区域设置相关的变量,以避免UTF-8解释,这对于碰巧包含违反UTF-8组合规则的字节序列的二进制文件可能会失败。在我对各种MVIMG文件的测试中,没有出现这样的问题。)

    推荐文章