Контекст и вопрос
Я записал видео с помощью своего телефона 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)