Вставить обложку альбома в OGG через командную строку в Linux

Я хочу преобразовать свою музыку из flac в ogg, и в настоящее время oggenc делает это отлично, за исключением обложек альбомов. Metaflac может выводить обложки альбомов, однако, похоже, что нет инструмента командной строки для встраивания обложек альбомов в ogg. MP3Tag и EasyTag могут сделать это, и здесь есть спецификация, которая требует, чтобы изображение было закодировано в base64. Однако до сих пор мне не удалось взять файл изображения, преобразовать его в base64 и встроить в файл ogg.

Если я возьму изображение в кодировке base64 из файла ogg, в который уже встроено изображение, я могу легко встроить его в другое изображение, используя vorbiscomment:

vorbiscomment -l withimage.ogg > textfile
vorbiscomment -c textfile noimage.ogg

Моя проблема заключается в том, чтобы взять что-то вроде JPEG и преобразовать его в base64. В настоящее время у меня есть:

base64 --wrap=0 ./image.jpg

Что дает мне файл изображения, преобразованный в base64, используя vorbiscomment и следуя правилам тегирования, я могу встроить его в файл ogg следующим образом:

echo "METADATA_BLOCK_PICTURE=$(base64 --wrap=0 ./image.jpg)" > ./folder.txt
vorbiscomment -c textfile noimage.ogg

Однако это дает мне ogg, изображение которого не работает должным образом. При сравнении строк base64 я заметил, что все правильно встраиваемые изображения имеют строку заголовка, но во всех генерируемых мной строках base64 этот заголовок отсутствует. Дальнейший анализ заголовка:

od -c header.txt
0000000  \0  \0  \0 003  \0  \0  \0  \n   i   m   a   g   e   /   j   p
0000020   e   g  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000040  \0  \0  \0  \0  \0  \0  \0  \0 035 332
0000052

Который следует спецификации, приведенной выше. Примечание 003 соответствует передней обложке, а image/jpeg - это пантомима.

Итак, наконец, мой вопрос, как я могу base64 кодировать файл и генерировать этот заголовок вместе с ним для встраивания в файл ogg?

6 ответов

Решение

Я только что написал скрипт, который экспортирует / импортирует изображения из файлов OGG/Vorbis с помощью vorbiscomment. Это часть инструмента преобразования музыкальной библиотеки.

Скромный скрипт находится в функции mussync-tools-Transfert_images этого инструмента:

https://github.com/biapy/howto.biapy.com/blob/master/various/mussync-tools

По сути, я написал программу для чтения и записи для формата metadata_block_picture.

Код довольно сложный:

      OUTPUT_FILE="/path/to/my-ogg-file.ogg"
      IMAGE_PATH="/path/to/my-cover-art.jpg"
      IMAGE_MIME_TYPE="image/jpeg"
      # Export existing comments to file.
      local COMMENTS_PATH="$(command mktemp -t "tmp.XXXXXXXXXX")"
      command vorbiscomment --list --raw "${OUTPUT_FILE}" > "${COMMENTS_PATH}"

      # Remove existing images.
      command sed -i -e '/^metadata_block_picture/d' "${COMMENTS_PATH}"

      # Insert cover image from file.

      # metadata_block_picture format.
      # See: https://xiph.org/flac/format.html#metadata_block_picture

      local IMAGE_WITH_HEADER="$(command mktemp -t "tmp.XXXXXXXXXX")"
      local DESCRIPTION=""

      # Reset cache file.
      echo -n "" > "${IMAGE_WITH_HEADER}"

      # Picture type <32>.
      command printf "0: %.8x" 3 | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Mime type length <32>.
      command printf "0: %.8x" $(echo -n "${IMAGE_MIME_TYPE}" | command wc -c) \
                | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Mime type (n * 8)
      echo -n "${IMAGE_MIME_TYPE}" >> "${IMAGE_WITH_HEADER}"
      # Description length <32>.
      command printf "0: %.8x" $(echo -n "${DESCRIPTION}" | command wc -c) \
                | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Description (n * 8)
      echo -n "${DESCRIPTION}" >> "${IMAGE_WITH_HEADER}"
      # Picture with <32>.
      command printf "0: %.8x" 0 | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Picture height <32>.
      command printf "0: %.8x" 0 | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Picture color depth <32>.
      command printf "0: %.8x" 0 | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Picture color count <32>.
      command printf "0: %.8x" 0 | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Image file size <32>.
      command printf "0: %.8x" $(command wc -c "${IMAGE_PATH}" \
                | command cut --delimiter=' ' --fields=1) \
                | command xxd -r -g0 \
              >> "${IMAGE_WITH_HEADER}"
      # Image file.
      command cat "${IMAGE_PATH}" >> "${IMAGE_WITH_HEADER}"

      echo "metadata_block_picture=$(command base64 --wrap=0 < "${IMAGE_WITH_HEADER}")" >> "${COMMENTS_PATH}"

      # Update vorbis file comments.
      command vorbiscomment --write --raw --commentfile "${COMMENTS_PATH}" "${OUTPUT_FILE}"

      # Delete cache file.
      command rm "${IMAGE_WITH_HEADER}"
      # Delete comments file.
      command rm "${COMMENTS_PATH}"

Вот мое решение для /usr/bin/vorbiscomment: Список аргументов слишком длинная. Я создал скрипт и назвал его oggart. Просто запустите его из командной строки следующим образом:

oggart /path/to/music_file.ogg /path/to/image_file

Это помечает ваш файл ogg с полем METADATA_BLOCK_PICTURE. Easytag использует старый способ сделать это с полем COVERART вместо METADATA_BLOCK_PICTURE. Если вам нужна совместимость с Easytag, вы можете запустить скрипт следующим образом:

oggart /path/to/music_file.ogg /path/to/image_file -e

Вот сценарий:

#!/bin/sh

FILE1="`basename \"$1\"`"
EXT1=${FILE1##*.}
EXTTYPE1=`echo $EXT1 | tr '[:upper:]' '[:lower:]'`

FILE2="`basename \"$2\"`"
EXT2=${FILE2##*.}
EXTTYPE2=`echo $EXT2 | tr '[:upper:]' '[:lower:]'`

OGG=""
if [ "$EXTTYPE1" = ogg ]; then
OGG="$1"
elif [ "$EXTTYPE2" = ogg ]; then
OGG="$2"
fi
if [ "$OGG" = "" ]; then
echo no ogg file selected
exit 0
fi

PIC=""
array=(jpeg jpg png)
for item in ${array[*]}
do
if [ "$item" = "$EXTTYPE1" ]; then
PIC="$1"
elif [ "$item" = "$EXTTYPE2" ]; then
PIC="$2"
fi
done
if [ "$PIC" = "" ]; then
echo no jpg or png file selected
exit 0
fi

if [ "$3" = -e ]; then
EASYTAG=Y
else
EASYTAG=N
fi

DESC=`basename "$PIC"`
APIC=`base64 --wrap=0 "$PIC"`
if [ "`which exiv2`" != "" ]; then
MIME=`exiv2 "$PIC" | grep 'MIME type ' | sed 's/: /|/' | cut -f 2 -d '|' | tail -n 1`
fi
if [ "$MIME" = "" ]; then
MIME="image/jpeg"
fi

vorbiscomment -l "$OGG" | grep -v '^COVERART=' | grep -v '^COVERARTDESCRIPTION=' | grep -v '^COVERARTMIME=' | grep -v 'METADATA_BLOCK_PICTURE=' > "$OGG".tags

if [ "$EASYTAG" = N ]; then
echo METADATA_BLOCK_PICTURE="$APIC" > "$OGG".tags2
else
echo COVERART="$APIC" > "$OGG".tags2
fi
vorbiscomment -w -R -c "$OGG".tags2 "$OGG"
vorbiscomment -a -R -t COVERARTDESCRIPTION="$DESC" "$OGG"
vorbiscomment -a -R -t COVERARTMIME="$MIME" "$OGG"
vorbiscomment -a -R -c "$OGG".tags "$OGG"

rm -f "$OGG".tags
rm -f "$OGG".tags2

Я не знаю ничего, что делает это автоматически, просто указывая на изображение.

Однако vorbiscomment может встраивать произвольные теги, вам просто нужно кодировать изображение в base64, а затем создать тег в правильном формате.

например vorbiscomment -a -t 'METADATA_BLOCK_PICTURE=...' file.ogg newfile.ogg

вам придется взломать эти шаги в какой-то скрипт, чтобы он был полезен.

ffmpeg можно использовать для обхода проблемы «слишком длинный список аргументов», о которой упоминали другие при попытке встроить большие файлы изображений.

      ffmpeg -i in.ogg -i metadata.dat -map_metadata 1 -codec copy out.ogg

где метаданные.dat — это текстовый файл, состоящий из:

      ;FFMETADATA1
METADATA_BLOCK_PICTURE=<img_blob64>

где <img_blob64> — это большой двоичный объект в кодировке Base64, созданный сценариями, предоставленными @biapy или @bob-smith.

Как и многие, кто прочитал этот пост, мне тоже нужен был способ помещать изображения в файлы ogg. У @Biapy все правильно, единственный способ — создать blob Metadata_block_picture.

Хотя решение Биапи чрезвычайно проясняющее, оно сложно только в том смысле, что за ним трудно следовать. Кроме того, это пофайлово, и мне нужен был BLOB-объект Base64, который можно было бы использовать для всех файлов в альбоме. Итак, основываясь на работе Биапи, я написал сценарий, который выводит только blob base64. Меня беспокоит определение ширины/высоты, но оно меня пока не подвело.

https://github.com/twopoint71/ogg-image-blobber

FFmpeg версии 4.4 автоматически поддерживает встраивание обложек альбомов в контейнеры Ogg с помощью видеокодека Theora (список поддерживаемых кодеков см. в разделе « Кодеки Ogg » в Википедии, хотя не все они могут поддерживаться FFmpeg).

Вот пример преобразования файла MP3 с видеодорожкой, содержащей обложку альбома, в файл Ogg со звуком в кодировке Opus и видео в кодировке Theora:

      $ ffprobe -hide_banner '01 - State of Grace.mp3' 
[mp3 @ 0x5594cbafe320] Estimating duration from bitrate, this may be inaccurate
Input #0, mp3, from '01 - State of Grace.mp3':
  Metadata:
    lyrics-eng      :  
    copyright       : š 2012 Big Machine Records, LLC.
    title           : State of Grace
    album_artist    : Taylor Swift
    album           : Red (Deluxe Version)
    date            : 2012
    track           : 01/22
    genre           : Country
    composer        : Taylor Swift
    disc            : 1/1
    comment         : Taylor Swift
  Duration: 00:04:55.81, start: 0.000000, bitrate: 321 kb/s
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 320 kb/s
  Stream #0:1: Video: mjpeg (Baseline), yuvj444p(pc, bt470bg/unknown/unknown), 600x600 [SAR 72:72 DAR 1:1], 90k tbr, 90k tbn, 90k tbc (attached pic)
    Metadata:
      title           : Cover
      comment         : Cover (front)
$ ffmpeg -hide_banner -i '01 - State of Grace.mp3' -c:a libopus -b:a 128000 -c:v libtheora -q:v 10 '01 - State of Grace.ogg'
[mp3 @ 0x55ebe6d3cc40] Estimating duration from bitrate, this may be inaccurate
Input #0, mp3, from '01 - State of Grace.mp3':
  Metadata:
    lyrics-eng      :  
    copyright       : š 2012 Big Machine Records, LLC.
    title           : State of Grace
    album_artist    : Taylor Swift
    album           : Red (Deluxe Version)
    date            : 2012
    track           : 01/22
    genre           : Country
    composer        : Taylor Swift
    disc            : 1/1
    comment         : Taylor Swift
  Duration: 00:04:55.81, start: 0.000000, bitrate: 321 kb/s
  Stream #0:0: Audio: mp3, 44100 Hz, stereo, fltp, 320 kb/s
  Stream #0:1: Video: mjpeg (Baseline), yuvj444p(pc, bt470bg/unknown/unknown), 600x600 [SAR 72:72 DAR 1:1], 90k tbr, 90k tbn, 90k tbc (attached pic)
    Metadata:
      title           : Cover
      comment         : Cover (front)
Stream mapping:
  Stream #0:1 -> #0:0 (mjpeg (native) -> theora (libtheora))
  Stream #0:0 -> #0:1 (mp3 (mp3float) -> opus (libopus))
Press [q] to stop, [?] for help
[swscaler @ 0x55ebe6db69e0] deprecated pixel format used, make sure you did set range correctly
[ogg @ 0x55ebe6d44c80] Frame rate very high for a muxer not efficiently supporting it.
Please consider specifying a lower framerate, a different muxer or -vsync 2
Output #0, ogg, to '01 - State of Grace.ogg':
  Metadata:
    lyrics-eng      :  
    copyright       : š 2012 Big Machine Records, LLC.
    title           : State of Grace
    album_artist    : Taylor Swift
    album           : Red (Deluxe Version)
    date            : 2012
    track           : 01/22
    genre           : Country
    composer        : Taylor Swift
    disc            : 1/1
    comment         : Taylor Swift
    encoder         : Lavf58.76.100
  Stream #0:0: Video: theora, yuv444p(tv, bt470bg/unknown/unknown, progressive), 600x600 [SAR 1:1 DAR 1:1], q=2-31, 200 kb/s, 90k fps, 90k tbn (attached pic)
    Metadata:
      title           : Cover
      DESCRIPTION     : Cover (front)
      encoder         : Lavc58.134.100 libtheora
      lyrics-eng      :  
      copyright       : š 2012 Big Machine Records, LLC.
      ALBUMARTIST     : Taylor Swift
      album           : Red (Deluxe Version)
      date            : 2012
      TRACKNUMBER     : 01/22
      genre           : Country
      composer        : Taylor Swift
      DISCNUMBER      : 1/1
  Stream #0:1: Audio: opus, 48000 Hz, stereo, flt, 128 kb/s
    Metadata:
      encoder         : Lavc58.134.100 libopus
      lyrics-eng      :  
      copyright       : š 2012 Big Machine Records, LLC.
      title           : State of Grace
      ALBUMARTIST     : Taylor Swift
      album           : Red (Deluxe Version)
      date            : 2012
      TRACKNUMBER     : 01/22
      genre           : Country
      composer        : Taylor Swift
      DISCNUMBER      : 1/1
      DESCRIPTION     : Taylor Swift
[mp3float @ 0x55ebe6d96360] Header missing time=00:04:31.63 bitrate=   0.1kbits/s speed=59.8x    64x    
Error while decoding stream #0:0: Invalid data found when processing input
frame=    1 fps=0.2 q=-0.0 Lsize=    4929kB time=00:04:55.79 bitrate= 136.5kbits/s speed=59.8x    
video:58kB audio:4830kB subtitle:0kB other streams:0kB global headers:3kB muxing overhead: 0.845459%
$ mpv '01 - State of Grace.ogg'
 (+) Video --vid=1 'Cover' (theora 600x600)
 (+) Audio --aid=1 'State of Grace' (opus 2ch 48000Hz)
AO: [alsa] 48000Hz stereo 2ch float
VO: [gpu] 600x600 yuv444p
(Paused) AV: -00:00:00 / 00:04:55 (0%)

Exiting... (Quit)
$ 

Более подробный ответ о том, как это сделать, я написал здесь: https://stackoverflow.com/a/70166081/17549713

Другие вопросы по тегам