Created
March 25, 2025 21:02
-
-
Save MrYakobo/67a59a5d8d08a6b2f9f88296d7bf3807 to your computer and use it in GitHub Desktop.
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 | |
import subprocess | |
import json | |
import os | |
import math | |
import sys | |
def human_readable_size(size_bytes): | |
"""Convert bytes to human-readable file size.""" | |
if size_bytes == 0: | |
return "0B" | |
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") | |
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 human_readable_duration(seconds): | |
"""Convert seconds to hours:minutes:seconds format.""" | |
hours = int(seconds // 3600) | |
minutes = int((seconds % 3600) // 60) | |
secs = int(seconds % 60) | |
return f"{hours:02d}:{minutes:02d}:{secs:02d}" | |
def get_media_info(file_path): | |
""" | |
Extract detailed media file information using ffprobe. | |
Args: | |
file_path (str): Path to the media file | |
Returns: | |
dict: Parsed media file information | |
""" | |
try: | |
# Command to get JSON output from ffprobe | |
command = [ | |
'ffprobe', | |
'-v', 'quiet', | |
'-print_format', 'json', | |
'-show_format', | |
'-show_streams', | |
file_path | |
] | |
# Run the command and capture output | |
result = subprocess.run(command, capture_output=True, text=True, check=True) | |
# Parse JSON output | |
media_info = json.loads(result.stdout) | |
# Prepare a more readable output | |
readable_info = { | |
'File Details': { | |
'Filename': os.path.basename(file_path), | |
'Full Path': file_path, | |
'File Size': human_readable_size(int(media_info['format'].get('size', 0))), | |
}, | |
'Format': media_info['format'].get('format_name', 'Unknown'), | |
'Duration': human_readable_duration(float(media_info['format'].get('duration', 0))), | |
'Streams': [] | |
} | |
# Process stream information | |
for stream in media_info.get('streams', []): | |
stream_info = { | |
'Type': stream.get('codec_type', 'Unknown'), | |
'Codec': stream.get('codec_name', 'Unknown'), | |
} | |
# Add specific details based on stream type | |
if stream.get('codec_type') == 'video': | |
stream_info.update({ | |
'Resolution': f"{stream.get('width', 'N/A')}x{stream.get('height', 'N/A')}", | |
'Framerate': stream.get('avg_frame_rate', 'N/A'), | |
'Pixel Format': stream.get('pix_fmt', 'Unknown') | |
}) | |
elif stream.get('codec_type') == 'audio': | |
stream_info.update({ | |
'Sample Rate': stream.get('sample_rate', 'N/A'), | |
'Channels': stream.get('channels', 'N/A'), | |
'Channel Layout': stream.get('channel_layout', 'Unknown') | |
}) | |
readable_info['Streams'].append(stream_info) | |
return readable_info | |
except subprocess.CalledProcessError as e: | |
print(f"Error running ffprobe: {e}") | |
return None | |
except json.JSONDecodeError: | |
print("Error parsing ffprobe output") | |
return None | |
except Exception as e: | |
print(f"Unexpected error: {e}") | |
return None | |
def main(): | |
""" | |
Main function to process media file information. | |
Accepts file path as a command-line argument. | |
""" | |
import math # Imported here to avoid global import | |
if len(sys.argv) < 2: | |
print("Usage: python script.py <media_file_path>") | |
sys.exit(1) | |
file_path = sys.argv[1] | |
if not os.path.exists(file_path): | |
print(f"File not found: {file_path}") | |
sys.exit(1) | |
# Get and print media information | |
media_info = get_media_info(file_path) | |
if media_info: | |
# Pretty print the media information | |
print("Media File Information:") | |
print("=" * 40) | |
# File Details | |
print("\nFile Details:") | |
for key, value in media_info['File Details'].items(): | |
print(f"{key}: {value}") | |
# Format and Duration | |
print(f"\nFormat: {media_info['Format']}") | |
print(f"Duration: {media_info['Duration']}") | |
# Streams | |
print("\nStreams:") | |
for i, stream in enumerate(media_info['Streams'], 1): | |
print(f"\nStream {i}:") | |
for key, value in stream.items(): | |
print(f"{key}: {value}") | |
if __name__ == "__main__": | |
main() |
Author
MrYakobo
commented
Mar 25, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment