Контекст и вопрос

Контекст и вопрос

Контекст и вопрос

Я записал видео с помощью своего телефона MotoG3 Android, и полученное видео (возможно, из-за тряски телефона) воспроизводится перевернутым, то есть вертикальным, что мне не нужно. Видео было сохранено в контейнере MP4.

При проверке записанного файла я увидел (используя ffprobeи mediainfo), что он содержит флаг, указывающий на то, что видеопоток повернут на 90 градусов, что объясняет поворот во время воспроизведения видео. Вот вывод из ffprobe:

$ ffprobe -hide_banner ~/Pictures/2016/06/19/vid_20160619_170845475.mp4 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/rbrito/Pictures/2016/06/19/vid_20160619_170845475.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2016-06-19 20:25:49
    com.android.version: 6.0
  Duration: 00:17:01.96, start: 0.000000, bitrate: 17134 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 17000 kb/s, SAR 1:1 DAR 16:9, 29 fps, 29.42 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      rotate          : 90
      creation_time   : 2016-06-19 20:25:49
      handler_name    : VideoHandle
      encoder         : MOTO
    Side data:
      displaymatrix: rotation of -90.00 degrees
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2016-06-19 20:25:49
      handler_name    : SoundHandle

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

К сожалению, используя информацию издругие ответыне помогло. Я пробовал использовать:

ffmpeg -i ~/Pictures/2016/06/19/vid_20160619_170845475.mp4 -c copy -metadata:s:v:0 rotate=0 -an vid_20160619_170845475_unrotated.mp4

Но другие метаданные, такие как дата и т. д., в результирующем файле отсутствуют. Это, в частности, сбивает с толку программы-органайзеры, показывая файлы по дате, среди прочего.

Есть ли способ минимально изменить входные данные (возможно, ремикшировать их), чтобы сохранить их как можно ближе к исходным данным? В частности, я не хочу перекодировать файл.

Предпочтительны любые инструменты, доступные под Linux.


Дополнительная информация

Поскольку был задан вопрос о полном выводе ffmpeg, вот он. Это чистое пользовательское пространство для тестирования Debian.

В качестве примечания, ffmpeg жалуется на несоответствующие библиотеки, потому что он компилируется дважды в Debian, один раз без потенциально проблемных кодеков, а другой с некоторыми дополнительными кодеками. Я использую версию с дополнительными кодеками, но полагаю, что это не имеет значения, поскольку здесь используется только мультиплексирование.

Метаданные перед ремикшированием

$ ffprobe  -hide_banner ~/Pictures/2016/06/19/vid_20160619_170845475.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/rbrito/Pictures/2016/06/19/vid_20160619_170845475.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2016-06-19 20:25:49
    com.android.version: 6.0
  Duration: 00:17:01.96, start: 0.000000, bitrate: 17134 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 17000 kb/s, SAR 1:1 DAR 16:9, 29 fps, 29.42 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      rotate          : 90
      creation_time   : 2016-06-19 20:25:49
      handler_name    : VideoHandle
      encoder         : MOTO
    Side data:
      displaymatrix: rotation of -90.00 degrees
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2016-06-19 20:25:49
      handler_name    : SoundHandle

Процесс ремикширования

Обратите внимание, что метаданные аудио не копируются (чего я и ожидал из-за наличия этой -metadata:s:v:0опции), а ffmpeg сообщает мне, что копируются метаданные видео (без настройки поворота).

$ ffmpeg -hide_banner -i ~/Pictures/2016/06/19/vid_20160619_170845475.mp4 -c copy -metadata:s:v:0 rotate=0 -an vid_20160619_170845475_unrotated.mp4 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/rbrito/Pictures/2016/06/19/vid_20160619_170845475.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    creation_time   : 2016-06-19 20:25:49
    com.android.version: 6.0
  Duration: 00:17:01.96, start: 0.000000, bitrate: 17134 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 17000 kb/s, SAR 1:1 DAR 16:9, 29 fps, 29.42 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      rotate          : 90
      creation_time   : 2016-06-19 20:25:49
      handler_name    : VideoHandle
      encoder         : MOTO
    Side data:
      displaymatrix: rotation of -90.00 degrees
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2016-06-19 20:25:49
      handler_name    : SoundHandle
Output #0, mp4, to 'vid_20160619_170845475_unrotated.mp4':
  Metadata:
    major_brand     : mp42
    minor_version   : 0
    compatible_brands: isommp42
    com.android.version: 6.0
    encoder         : Lavf57.25.100
    Stream #0:0(eng): Video: h264 ([33][0][0][0] / 0x0021), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 17000 kb/s, 29 fps, 29.42 tbr, 90k tbn, 90k tbc (default)
    Metadata:
      encoder         : MOTO
      creation_time   : 2016-06-19 20:25:49
      handler_name    : VideoHandle
      rotate          : 0
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame=29640 fps=403 q=-1.0 Lsize= 2121038kB time=00:17:01.91 bitrate=17003.0kbits/s speed=13.9x    
video:2120800kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.011211%

Метаданные после ремикширования

Обратите внимание, что в выходных данных нет метаданных видео, есть только метаданные уровня контейнера.

$ ffprobe -hide_banner vid_20160619_170845475_unrotated.mp4 
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'vid_20160619_170845475_unrotated.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.25.100
  Duration: 00:17:01.95, start: 0.000000, bitrate: 17002 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080, 17000 kb/s, 29 fps, 29.42 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      handler_name    : VideoHandler

решение1

По умолчанию FFmpeg не переносит большую часть пользовательских метаданных, но переносит такие поля, как тег ротации.

Приведенная ниже команда дает команду FFmpeg перенести все метаданные, но затем переопределяет значение тега ротации.

ffmpeg -i in.mp4 -c copy -map_metadata 0 -metadata:s:v:0 rotate=0 -an out.mp4

решение2

Выполните эту команду:

ffmpeg -i oldfile.mp4 -codec copy -metadata title="" -metadata album="" -metadata year="" -metadata container="" -metadata artist="" -metadata comment="" newfile.mp4

При использовании "" в каждом типе метаданных старые метаданные будут очищены, а затем ffmpeg скопирует весь файл в новый файл с очищенными метаданными.

После создания нового файла вам придется удалить старый файл, чтобы избежать дубликатов.

решение3

  • Установите библиотеку Python Mutagen:

    python3.6 -m pip install --user mutagen
    

    или:

    python2.7 -m pip install --user mutagen
    

    Mutagen — это модуль Python для обработки аудиометаданных.

  • Сохраните приведенный ниже контент как, metadata_cleaner.pyно вы можете назвать его как угодно.

  • Измените VIDEO_FOLDER = 'your_full_path_for_your_videos_folder'переменную.

  • Измените атрибуты, которые вы хотите перезаписать, между строками, где написано «Ваши изменения».

  • Бегите python metadata_cleaner.pyкуда угодно.

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

import os
from mutagen.mp4 import MP4
## Can import MP3 as well if you want to modify MP3 files

## Folder full path to the files you want to modify:

FILES_FOLDER = "/media/removable/64GB-Micro/FilesToClean"

def get_all_files(path):
    """Returns all the files in the path as a list
    """
    return os.listdir(path)

def clean_metadata(videos_dir, files):
    """
    Receives two variables videos_dir (full file folder path) and files (list)
    Iterates over all the files in the directory and creates full paths for 
    every file using the videos_dir path and os.path.join function.
    """
    for file_name in files:
        file_path = os.path.join(videos_dir, file_name)

        ## create MP4 video_file instance

        video_file = MP4(file_path)

        ## This line will print out all key-value for the video_file-s:
        ## Useful if you don't know which attributes you want to modify yet

        print(video_file)

        ## In this example I wanted to clean the ART, aArt = Artist metadata
        ## and nam = Song Name metadata
        ## These prints will show artists and titles for each file before clean
        ## -------------------------- Your changes ---------------------------
        print("file_name: {}".format(file_name))
        print("Old ART: {}".format(video_file.get('\xa9ART', "Key not found")))
        print("Old aArt: {}".format(video_file.get('aART', "Key not found")))
        print("Old nam: {}".format(video_file.get('\xa9nam', "Key not found")))

        ## clean artist and name
        ## This part will overwrite the artist and song name attributes

        video_file['\xa9ART'] = ''
        video_file['aART'] = ''
        video_file['\xa9nam'] = ''
        ## -------------------------- Your changes ---------------------------
        ## save new metadata

        video_file.save()

        ## show video_file artist and title after clean
        ## Just to see if our actions were successful print out song metadata
        ## again after the changes

        print("New ART: {}".format(video_file.get('\xa9ART', "Key not found")))
        print("New aArt: {}".format(video_file.get('aART', "Key not found")))
        print("New nam: {}".format(video_file.get('\xa9nam', "Key not found")))


if __name__ == '__main__':
    ## load all the files into files variable as a list

    files = get_all_files(FILES_FOLDER)

    ## run clean_metadata function to clean all the files in the VIDEO_FOLDER
    ## path
    clean_metadata(videos_dir=FILES_FOLDER, files=files)

Связанный контент