[READ-ONLY] Mirror of https://github.com/mrgnw/scripts.
0

Configure Feed

Select the types of activity you want to include in your feed.

scripts / ffprobe_sum_times
1.7 kB 76 lines
1#!/usr/bin/env python3 2 3import subprocess 4from pathlib import Path 5import sys 6from concurrent.futures import ThreadPoolExecutor, as_completed 7import os 8 9 10def main(): 11 files = get_files(sys.argv[1:]) 12 with ThreadPoolExecutor(max_workers=32) as executor: 13 future_to_file = {executor.submit(get_duration, file): file for file in files} 14 durations = { 15 str(future_to_file[future]): future.result() 16 for future in as_completed(future_to_file) 17 if future.result() > 0 18 } 19 dur_strs = [f'{format_time(duration)}\t{file}' for file, duration in durations.items()] 20 print('\n'.join(dur_strs)) 21 total_seconds = sum(durations.values()) 22 print('Total playtime:', format_time(total_seconds)) 23 24 25def get_files(args): 26 files = [] 27 if not args: 28 files.extend(scan_directory('.')) 29 else: 30 for arg in args: 31 path = Path(arg) 32 if path.is_dir(): 33 files.extend(scan_directory(arg)) 34 else: 35 files.extend(scan_directory('.', pattern=arg)) 36 return [file for file in files if file.is_file()] 37 38 39def scan_directory(directory, pattern='*'): 40 with os.scandir(directory) as it: 41 for entry in it: 42 if entry.is_file() and Path(entry.name).match(pattern): 43 yield Path(entry.path) 44 45 46def get_duration(filename): 47 try: 48 result = subprocess.run( 49 [ 50 'ffprobe', 51 '-v', 52 'error', 53 '-show_entries', 54 'format=duration', 55 '-of', 56 'default=noprint_wrappers=1:nokey=1', 57 filename, 58 ], 59 stdout=subprocess.PIPE, 60 stderr=subprocess.STDOUT, 61 universal_newlines=True, 62 ) 63 return float(result.stdout.strip()) 64 except Exception: 65 return 0 66 67 68def format_time(seconds): 69 h = int(seconds // 3600) 70 m = int((seconds % 3600) // 60) 71 s = int(seconds % 60) 72 return f'{h:2d}h {m:2d}m {s:2d}s' 73 74 75if __name__ == '__main__': 76 main()