Kontext und Frage
Ich habe mit meinem Android-Telefon MotoG3 ein Video aufgenommen und das resultierende Video (möglicherweise aufgrund des Schüttelns des Telefons) wird gedreht, also vertikal, abgespielt, was ich nicht möchte. Das Video wurde in einem MP4-Container gespeichert.
Beim Überprüfen der aufgezeichneten Datei habe ich (unter Verwendung von ffprobe
und mediainfo
) festgestellt, dass sie ein Flag enthält, das angibt, dass der Videostream um 90 Grad gedreht ist, was die Drehung während der Wiedergabe des Videos erklärt. Hier ist die Ausgabe von 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
Da dieses Video von einem seltenen Ereignis mit meinem Sohn stammt, möchte ich die Videodatei nur minimal ändern, vorzugsweise nur die Rotationsmetadaten entfernen und sonst nichts.
Leider verwenden wir Informationen ausAndere Antworthat nicht geholfen. Ich habe versucht:
ffmpeg -i ~/Pictures/2016/06/19/vid_20160619_170845475.mp4 -c copy -metadata:s:v:0 rotate=0 -an vid_20160619_170845475_unrotated.mp4
Andere Metadaten wie Datum etc. sind in der resultierenden Datei jedoch nicht vorhanden. Dies führt insbesondere bei Organizer-Programmen zu Verwirrungen, wenn diese die Dateien u.a. nach Datum anzeigen.
Gibt es eine Möglichkeit, die Eingabedaten minimal zu verändern (möglicherweise durch Remuxen), um sie möglichst nah an den Originaldaten zu halten? Insbesondere möchte ich die Datei nicht neu kodieren.
Alle unter Linux verfügbaren Tools werden bevorzugt.
Zusatzinformation
Da die vollständige Ausgabe von ffmpeg angefordert wurde, ist sie hier. Dies ist ein reines Debian-Testbenutzerland.
Nebenbei bemerkt beschwert sich ffmpeg über nicht übereinstimmende Bibliotheken, da es in Debian zweimal kompiliert wird, einmal ohne potenziell problematische Codecs und einmal mit einigen zusätzlichen Codecs. Ich verwende die Version mit zusätzlichen Codecs, aber ich nehme an, dass das keine Rolle spielt, da hier nur das Multiplexen verwendet wird.
Metadaten vor dem Remuxen
$ 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
Der Remuxing-Prozess
Beachten Sie hier, dass die Audio-Metadaten nicht kopiert werden (was ich aufgrund der -metadata:s:v:0
Option erwartet hatte) und ffmpeg mir mitteilt, dass es die Video-Metadaten kopiert (ohne die Rotationseinstellung).
$ 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%
Metadaten nach dem Remuxing
Beachten Sie hierbei, dass die Ausgabe keine Videometadaten enthält, sondern nur Metadaten auf Containerebene.
$ 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
Antwort1
FFmpeg überträgt standardmäßig nicht die meisten Benutzermetadaten, aber es überträgt Felder wie das Rotationstag.
Der folgende Befehl weist FFmpeg an, alle Metadaten zu übertragen, überschreibt dann jedoch den Rotations-Tag-Wert.
ffmpeg -i in.mp4 -c copy -map_metadata 0 -metadata:s:v:0 rotate=0 -an out.mp4
Antwort2
Führen Sie diesen Befehl aus:
ffmpeg -i oldfile.mp4 -codec copy -metadata title="" -metadata album="" -metadata year="" -metadata container="" -metadata artist="" -metadata comment="" newfile.mp4
Durch die Verwendung von "" in jedem Metadatentyp werden alte Metadaten geleert und ffmpeg kopiert dann die gesamte Datei mit gelöschten Metadaten in eine neue Datei.
Um Duplikate zu vermeiden, müssen Sie nach dem Erstellen einer neuen Datei die alte Datei löschen.
Antwort3
Installieren Sie die Mutagen-Python-Bibliothek:
python3.6 -m pip install --user mutagen
oder:
python2.7 -m pip install --user mutagen
Mutagen ist ein Python-Modul zur Verarbeitung von Audio-Metadaten.
Speichern Sie den folgenden Inhalt unter „,
metadata_cleaner.py
Sie können ihm aber einen beliebigen Namen geben.“Ändern Sie die
VIDEO_FOLDER = 'your_full_path_for_your_videos_folder'
Variable.Ändern Sie die Attribute, die Sie überschreiben möchten, zwischen den Zeilen mit dem Text „Ihre Änderungen“.
Laufen Sie
python metadata_cleaner.py
überall hin.
Hier ist das Skript:
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)