Last active
September 11, 2024 12:30
-
-
Save adde88/2f61e245b197675a02d18fccd14fe523 to your computer and use it in GitHub Desktop.
Script to analyze movie files, to output important information for me. Like filename, filesize, codec, bit-rate, dimensions. More to cum
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"PresetList": [ | |
{ | |
"AlignAVStart": true, | |
"AudioCopyMask": [ | |
"copy:aac" | |
], | |
"AudioEncoderFallback": "av_aac", | |
"AudioLanguageList": [], | |
"AudioList": [ | |
{ | |
"AudioBitrate": 160, | |
"AudioCompressionLevel": -1.0, | |
"AudioDitherMethod": "auto", | |
"AudioEncoder": "av_aac", | |
"AudioMixdown": "stereo", | |
"AudioNormalizeMixLevel": false, | |
"AudioSamplerate": "auto", | |
"AudioTrackDRCSlider": 0.0, | |
"AudioTrackGainSlider": 0.0, | |
"AudioTrackQuality": 1.0, | |
"AudioTrackQualityEnable": false | |
} | |
], | |
"AudioSecondaryEncoderMode": true, | |
"AudioTrackSelectionBehavior": "first", | |
"ChapterMarkers": true, | |
"ChildrenArray": [], | |
"Default": false, | |
"FileFormat": "av_mp4", | |
"Folder": false, | |
"FolderOpen": false, | |
"InlineParameterSets": false, | |
"MetadataPassthrough": true, | |
"Mp4HttpOptimize": true, | |
"Mp4iPodCompatible": false, | |
"PictureAllowUpscaling": false, | |
"PictureAutoCrop": true, | |
"PictureBottomCrop": 0, | |
"PictureChromaSmoothCustom": "", | |
"PictureChromaSmoothPreset": "off", | |
"PictureChromaSmoothTune": "none", | |
"PictureColorspaceCustom": "", | |
"PictureColorspacePreset": "off", | |
"PictureCombDetectCustom": "", | |
"PictureCombDetectPreset": "off", | |
"PictureDARWidth": 1920, | |
"PictureDeblockCustom": "strength=strong:thresh=20:blocksize=8", | |
"PictureDeblockPreset": "off", | |
"PictureDeblockTune": "medium", | |
"PictureDeinterlaceCustom": "", | |
"PictureDeinterlaceFilter": "off", | |
"PictureDeinterlacePreset": "", | |
"PictureDenoiseCustom": "", | |
"PictureDenoiseFilter": "off", | |
"PictureDenoisePreset": "", | |
"PictureDenoiseTune": "none", | |
"PictureDetelecine": "off", | |
"PictureDetelecineCustom": "", | |
"PictureForceHeight": 0, | |
"PictureForceWidth": 0, | |
"PictureHeight": 1080, | |
"PictureItuPAR": false, | |
"PictureKeepRatio": true, | |
"PictureLeftCrop": 0, | |
"PictureLooseCrop": false, | |
"PictureModulus": 2, | |
"PicturePAR": "auto", | |
"PicturePARHeight": 1, | |
"PicturePARWidth": 1, | |
"PicturePadBottom": 0, | |
"PicturePadColor": "black", | |
"PicturePadLeft": 0, | |
"PicturePadMode": "none", | |
"PicturePadRight": 0, | |
"PicturePadTop": 0, | |
"PictureRightCrop": 0, | |
"PictureRotate": "angle=0:hflip=0", | |
"PictureSharpenCustom": "", | |
"PictureSharpenFilter": "off", | |
"PictureSharpenPreset": "", | |
"PictureSharpenTune": "", | |
"PictureTopCrop": 0, | |
"PictureUseMaximumSize": true, | |
"PictureWidth": 1920, | |
"PresetDescription": "Small H.264 video (up to 1080p30) and AAC stereo audio, in an MP4 container.", | |
"PresetDisabled": false, | |
"PresetName": "Very Fast 1080p30 (modified)", | |
"SubtitleAddCC": false, | |
"SubtitleAddForeignAudioSearch": true, | |
"SubtitleAddForeignAudioSubtitle": false, | |
"SubtitleBurnBDSub": true, | |
"SubtitleBurnBehavior": "foreign", | |
"SubtitleBurnDVDSub": true, | |
"SubtitleLanguageList": [], | |
"SubtitleTrackSelectionBehavior": "none", | |
"Type": 1, | |
"UsesPictureFilters": true, | |
"VideoAvgBitrate": 2000, | |
"VideoColorMatrixCodeOverride": 0, | |
"VideoEncoder": "nvenc_h264", | |
"VideoFramerate": "30", | |
"VideoFramerateMode": "cfr", | |
"VideoGrayScale": false, | |
"VideoLevel": "auto", | |
"VideoOptionExtra": "", | |
"VideoPreset": "medium", | |
"VideoProfile": "auto", | |
"VideoQSVDecode": false, | |
"VideoQualitySlider": 15.0, | |
"VideoQualityType": 1, | |
"VideoScaler": "swscale", | |
"VideoTune": "", | |
"VideoTurboTwoPass": true, | |
"VideoTwoPass": false, | |
"x264Option": "", | |
"x264UseAdvancedOptions": false | |
} | |
], | |
"VersionMajor": 47, | |
"VersionMicro": 0, | |
"VersionMinor": 0 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"PresetList": [ | |
{ | |
"AlignAVStart": true, | |
"AudioCopyMask": [ | |
"copy:aac" | |
], | |
"AudioEncoderFallback": "av_aac", | |
"AudioLanguageList": [], | |
"AudioList": [ | |
{ | |
"AudioBitrate": 160, | |
"AudioCompressionLevel": -1.0, | |
"AudioDitherMethod": "auto", | |
"AudioEncoder": "av_aac", | |
"AudioMixdown": "stereo", | |
"AudioNormalizeMixLevel": false, | |
"AudioSamplerate": "auto", | |
"AudioTrackDRCSlider": 0.0, | |
"AudioTrackGainSlider": 0.0, | |
"AudioTrackQuality": 1.0, | |
"AudioTrackQualityEnable": false | |
} | |
], | |
"AudioSecondaryEncoderMode": true, | |
"AudioTrackSelectionBehavior": "first", | |
"ChapterMarkers": true, | |
"ChildrenArray": [], | |
"Default": true, | |
"FileFormat": "av_mp4", | |
"Folder": false, | |
"FolderOpen": false, | |
"InlineParameterSets": false, | |
"MetadataPassthrough": true, | |
"Mp4HttpOptimize": true, | |
"Mp4iPodCompatible": false, | |
"PictureAllowUpscaling": false, | |
"PictureAutoCrop": true, | |
"PictureBottomCrop": 0, | |
"PictureChromaSmoothCustom": "", | |
"PictureChromaSmoothPreset": "off", | |
"PictureChromaSmoothTune": "none", | |
"PictureColorspaceCustom": "", | |
"PictureColorspacePreset": "off", | |
"PictureCombDetectCustom": "", | |
"PictureCombDetectPreset": "off", | |
"PictureDARWidth": 1920, | |
"PictureDeblockCustom": "strength=strong:thresh=20:blocksize=8", | |
"PictureDeblockPreset": "off", | |
"PictureDeblockTune": "medium", | |
"PictureDeinterlaceCustom": "", | |
"PictureDeinterlaceFilter": "off", | |
"PictureDeinterlacePreset": "", | |
"PictureDenoiseCustom": "", | |
"PictureDenoiseFilter": "off", | |
"PictureDenoisePreset": "", | |
"PictureDenoiseTune": "none", | |
"PictureDetelecine": "off", | |
"PictureDetelecineCustom": "", | |
"PictureForceHeight": 0, | |
"PictureForceWidth": 0, | |
"PictureHeight": 1080, | |
"PictureItuPAR": false, | |
"PictureKeepRatio": true, | |
"PictureLeftCrop": 0, | |
"PictureLooseCrop": false, | |
"PictureModulus": 2, | |
"PicturePAR": "auto", | |
"PicturePARHeight": 1, | |
"PicturePARWidth": 1, | |
"PicturePadBottom": 0, | |
"PicturePadColor": "black", | |
"PicturePadLeft": 0, | |
"PicturePadMode": "none", | |
"PicturePadRight": 0, | |
"PicturePadTop": 0, | |
"PictureRightCrop": 0, | |
"PictureRotate": "angle=0:hflip=0", | |
"PictureSharpenCustom": "", | |
"PictureSharpenFilter": "off", | |
"PictureSharpenPreset": "", | |
"PictureSharpenTune": "", | |
"PictureTopCrop": 0, | |
"PictureUseMaximumSize": true, | |
"PictureWidth": 1920, | |
"PresetDescription": "Small H.264 video (up to 1080p30) and AAC stereo audio, in an MP4 container.", | |
"PresetDisabled": false, | |
"PresetName": "Very Fast 1080p30", | |
"SubtitleAddCC": false, | |
"SubtitleAddForeignAudioSearch": true, | |
"SubtitleAddForeignAudioSubtitle": false, | |
"SubtitleBurnBDSub": true, | |
"SubtitleBurnBehavior": "foreign", | |
"SubtitleBurnDVDSub": true, | |
"SubtitleLanguageList": [], | |
"SubtitleTrackSelectionBehavior": "none", | |
"Type": 1, | |
"UsesPictureFilters": true, | |
"VideoAvgBitrate": 2000, | |
"VideoColorMatrixCodeOverride": 0, | |
"VideoEncoder": "nvenc_h265", | |
"VideoFramerate": "30", | |
"VideoFramerateMode": "cfr", | |
"VideoGrayScale": false, | |
"VideoLevel": "auto", | |
"VideoOptionExtra": "", | |
"VideoPreset": "medium", | |
"VideoProfile": "auto", | |
"VideoQSVDecode": false, | |
"VideoQualitySlider": 15.0, | |
"VideoQualityType": 1, | |
"VideoScaler": "swscale", | |
"VideoTune": "", | |
"VideoTurboTwoPass": true, | |
"VideoTwoPass": false, | |
"x264Option": "", | |
"x264UseAdvancedOptions": false | |
} | |
], | |
"VersionMajor": 47, | |
"VersionMicro": 0, | |
"VersionMinor": 0 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# Made by: Andreas Nilsen - @adde88 - <[email protected]> | |
# Script to analyze movie files, and print out some details about them | |
# It can also be used to compress files that has not been compressed by this script earlier | |
# It uses HandBrakeCLI to compress the files, so make sure you have installed that as well as the python libraries being used, such as tqdm. | |
# I attempted using ffmpeg-python to compress the files, but it was more user friendly to use this option. | |
# | |
# PLEASE REMEMBER TO EDIT LINE 72 (inside the code-block where the 'compress_file' function is defined)!!! | |
import os | |
import sys | |
import subprocess | |
import json | |
import math | |
import time | |
import threading | |
from datetime import datetime | |
from tqdm import tqdm | |
import re | |
def get_file_size(file_path): | |
return os.path.getsize(file_path) | |
def convert_size(size_bytes): | |
if size_bytes == 0: | |
return "0B" | |
size_name = ("B", "KB", "MB", "GB", "TB") | |
i = int(math.floor(math.log(size_bytes, 1024))) | |
p = math.pow(1024, i) | |
s = round(size_bytes / p, 2) | |
return f"{s} {size_name[i]}" | |
def convert_bitrate(bitrate_bps): | |
if bitrate_bps == "N/A": | |
return "N/A" | |
bitrate_bps = int(bitrate_bps) | |
if bitrate_bps == 0: | |
return "0 bps" | |
size_name = ("bps", "Kbps", "Mbps", "Gbps", "Tbps") | |
i = int(math.floor(math.log(bitrate_bps, 1000))) | |
p = math.pow(1000, i) | |
s = round(bitrate_bps / p, 2) | |
return f"{s} {size_name[i]}" | |
def get_movie_details(file_path): | |
command = [ | |
'ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', | |
'stream=codec_name,bit_rate,width,height', '-of', 'json', file_path | |
] | |
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | |
if result.returncode != 0: | |
raise Exception(f"ffprobe error: {result.stderr}") | |
details = json.loads(result.stdout) | |
stream = details['streams'][0] | |
return { | |
'codec': stream['codec_name'], | |
'bit_rate': stream.get('bit_rate', 'N/A'), | |
'width': stream['width'], | |
'height': stream['height'] | |
} | |
def get_file_dates(file_path): | |
creation_time = os.path.getctime(file_path) | |
modification_time = os.path.getmtime(file_path) | |
creation_date = datetime.fromtimestamp(creation_time).strftime('%d. %B %Y @ %H:%M:%S') | |
modification_date = datetime.fromtimestamp(modification_time).strftime('%d. %B %Y @ %H:%M:%S') | |
return creation_date, modification_date | |
def compress_file(file_path, codec_choice): | |
# Please edit this line below to point to the correct location you donloaded the preset files i added | |
preset_path = "/home/andreas/hb-imports-265.json" if codec_choice == 'h265_nvenc' else "/home/andreas/hb-imports-264.json" | |
output_path = os.path.join(os.path.dirname(file_path), f"Compressed-{os.path.basename(file_path)}") | |
# Check if the compressed file already exists | |
if os.path.exists(output_path): | |
print(f"The file '{output_path}' already exists. Skipping compression.") | |
return output_path | |
print("Please wait and be patient, compressing file, this will take a little while...") | |
start_time = time.time() | |
def print_elapsed_time(): | |
while not stop_timer: | |
elapsed_time = time.time() - start_time | |
print(f"Elapsed time: {int(elapsed_time)} seconds", end='\r') | |
time.sleep(1) | |
stop_timer = False | |
timer_thread = threading.Thread(target=print_elapsed_time) | |
timer_thread.start() | |
command = [ | |
'HandBrakeCLI', '-i', file_path, '-o', output_path, '--preset-import-file', preset_path | |
] | |
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | |
process.wait() | |
stop_timer = True | |
timer_thread.join() | |
total_time = time.time() - start_time | |
if process.returncode != 0: | |
print(f"HandBrakeCLI error: {process.stderr.read()}") | |
else: | |
print(f"\nFile compressed successfully: {output_path}") | |
print(f"Total compression time: {int(total_time)} seconds") | |
return output_path | |
def analyze_file(file_path): | |
file_size = get_file_size(file_path) | |
movie_details = get_movie_details(file_path) | |
creation_date, modification_date = get_file_dates(file_path) | |
print(f"Filename: {file_path}") | |
print(f"Filesize: {convert_size(file_size)}") | |
print(f"Codec: {movie_details['codec']}") | |
print(f"Bit-rate: {convert_bitrate(movie_details['bit_rate'])}") | |
print(f"Dimensions: {movie_details['width']}x{movie_details['height']}") | |
print(f"Created: {creation_date}") | |
print(f"Modified: {modification_date}") | |
def main(): | |
if len(sys.argv) != 2: | |
print("Usage: python3 movie_analyze.py <movie_name>") | |
sys.exit(1) | |
file_path = sys.argv[1] | |
if not os.path.isfile(file_path): | |
print(f"File was not found: {file_path}") | |
sys.exit(1) | |
analyze_file(file_path) | |
compress = input("\nDo you want to compress the file? (yes/no): ").strip().lower() | |
if compress == 'yes': | |
codec_choice = input("Choose codec (1: h264_nvenc, 2: h265_nvenc): ").strip() | |
if codec_choice == '1': | |
codec_choice = 'h264_nvenc' | |
elif codec_choice == '2' or codec_choice == '': | |
codec_choice = 'h265_nvenc' | |
else: | |
print("Invalid codec choice. Exiting.") | |
sys.exit(1) | |
compressed_file_path = compress_file(file_path, codec_choice) | |
if compressed_file_path: | |
analyze_new = input("\nDo you want to analyze the compressed file? (yes/no): ").strip().lower() | |
if analyze_new == 'yes': | |
analyze_file(compressed_file_path) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment