File size: 3,777 Bytes
773f76d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import subprocess
from functools import lru_cache
from typing import Dict, List
from facefusion import ffprobe_builder
from facefusion.types import AudioMetadata, Buffer, Command, Fps, VideoMetadata
def run_ffprobe(commands : List[Command]) -> subprocess.Popen[Buffer]:
commands = ffprobe_builder.run(commands)
return subprocess.Popen(commands, stderr = subprocess.PIPE, stdout = subprocess.PIPE)
def parse_entries(output : Buffer) -> Dict[str, str]:
media_entries = {}
if output:
lines = output.decode().strip().splitlines()
for line in lines:
if '=' in line:
key, value = line.split('=', 1)
media_entries[key] = value
return media_entries
def probe_audio_entries(audio_path : str, entries : List[str]) -> Dict[str, str]:
commands = ffprobe_builder.chain(
ffprobe_builder.select_stream('a:0'),
ffprobe_builder.show_stream_entries(entries),
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(audio_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
def probe_video_entries(video_path : str, entries : List[str]) -> Dict[str, str]:
commands = ffprobe_builder.chain(
ffprobe_builder.select_stream('v:0'),
ffprobe_builder.show_stream_entries(entries),
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(video_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
def probe_format_entries(media_path : str, entries : List[str]) -> Dict[str, str]:
commands = ffprobe_builder.chain(
ffprobe_builder.show_format_entries(entries),
ffprobe_builder.format_to_key_value(),
ffprobe_builder.set_input(media_path)
)
output, _ = run_ffprobe(commands).communicate()
return parse_entries(output)
@lru_cache(maxsize = 128)
def extract_static_audio_metadata(audio_path : str) -> AudioMetadata:
return extract_audio_metadata(audio_path)
def extract_audio_metadata(audio_path : str) -> AudioMetadata:
audio_entries = probe_audio_entries(audio_path, [ 'sample_rate', 'channels' ])
format_entries = probe_format_entries(audio_path, [ 'duration', 'bit_rate' ])
duration = float(format_entries.get('duration'))
sample_rate = int(audio_entries.get('sample_rate'))
frame_total = round(duration * sample_rate)
channel_total = int(audio_entries.get('channels'))
bit_rate = int(format_entries.get('bit_rate'))
audio_metadata : AudioMetadata =\
{
'duration' : duration,
'frame_total' : frame_total,
'channel_total' : channel_total,
'sample_rate' : sample_rate,
'bit_rate' : bit_rate
}
return audio_metadata
@lru_cache(maxsize = 128)
def extract_static_video_metadata(video_path : str) -> VideoMetadata:
return extract_video_metadata(video_path)
def extract_video_metadata(video_path : str) -> VideoMetadata:
video_entries = probe_video_entries(video_path, [ 'width', 'height', 'r_frame_rate', 'color_transfer' ])
format_entries = probe_format_entries(video_path, [ 'duration', 'bit_rate' ])
duration = float(format_entries.get('duration'))
fps = extract_video_fps(video_entries.get('r_frame_rate'))
frame_total = round(duration * fps)
width = int(video_entries.get('width'))
height = int(video_entries.get('height'))
bit_rate = int(format_entries.get('bit_rate'))
color_transfer = video_entries.get('color_transfer', 'unknown')
video_metadata : VideoMetadata =\
{
'duration' : duration,
'frame_total' : frame_total,
'fps' : fps,
'resolution' : (width, height),
'bit_rate' : bit_rate,
'color_transfer' : color_transfer
}
return video_metadata
def extract_video_fps(frame_rate : str) -> Fps:
if frame_rate and '/' in frame_rate:
numerator, denominator = frame_rate.split('/')
if int(numerator) and int(denominator):
return int(numerator) / int(denominator)
return 0.0
|