Remove python prototype scripts
This commit is contained in:
@@ -1,79 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import json
|
|
||||||
from collections import Counter
|
|
||||||
|
|
||||||
def detect_crop(file_path):
|
|
||||||
cmd = [
|
|
||||||
'ffmpeg',
|
|
||||||
'-skip_frame', 'nokey',
|
|
||||||
'-i', file_path,
|
|
||||||
'-vf', 'cropdetect=limit=24/255:round=16:reset=0',
|
|
||||||
'-f', 'null',
|
|
||||||
'-'
|
|
||||||
]
|
|
||||||
|
|
||||||
process = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
|
|
||||||
crop_pattern = re.compile(r'crop=([0-9]+):([0-9]+):([0-9]+):([0-9]+)')
|
|
||||||
|
|
||||||
crops = []
|
|
||||||
|
|
||||||
for line in process.stderr:
|
|
||||||
match = crop_pattern.search(line)
|
|
||||||
if match:
|
|
||||||
w, h, x, y = map(int, match.groups())
|
|
||||||
# ignorujemy calkowicie ciemne klatki (gdzie cropdetect ucina z kazdej strony)
|
|
||||||
# interesuje nas glownie format wideo (np proporcje)
|
|
||||||
crops.append((w, h, x, y))
|
|
||||||
|
|
||||||
process.wait()
|
|
||||||
|
|
||||||
if not crops:
|
|
||||||
return {"error": "No crop detected"}
|
|
||||||
|
|
||||||
# Policz jak często występuje dany crop
|
|
||||||
crop_counts = Counter(crops)
|
|
||||||
total_frames = len(crops)
|
|
||||||
|
|
||||||
# Filtrujemy losowe błędy i czarne plansze (szukamy cropów które występują co najmniej w 5% klatek kluczowych)
|
|
||||||
valid_crops = [c for c, count in crop_counts.items() if count / total_frames > 0.05]
|
|
||||||
|
|
||||||
if not valid_crops:
|
|
||||||
# Jeśli nic nie przekracza 5%, bierzemy po prostu najczęstszy
|
|
||||||
valid_crops = [crop_counts.most_common(1)[0][0]]
|
|
||||||
|
|
||||||
# Z valid_crops wybieramy taki "safe crop", który jest obwiednią (bounding box)
|
|
||||||
# dla wszystkich ISTOTNYCH proporcji w filmie.
|
|
||||||
# To pozwoli na zachowanie scen IMAX, a odcięcie stałych czarnych pasów.
|
|
||||||
|
|
||||||
min_x = min(c[2] for c in valid_crops)
|
|
||||||
min_y = min(c[3] for c in valid_crops)
|
|
||||||
max_xw = max(c[2] + c[0] for c in valid_crops)
|
|
||||||
max_yh = max(c[3] + c[1] for c in valid_crops)
|
|
||||||
|
|
||||||
safe_crop = {
|
|
||||||
"w": max_xw - min_x,
|
|
||||||
"h": max_yh - min_y,
|
|
||||||
"x": min_x,
|
|
||||||
"y": min_y
|
|
||||||
}
|
|
||||||
|
|
||||||
most_common_tuple = crop_counts.most_common(1)[0][0]
|
|
||||||
most_common = f"{most_common_tuple[0]}:{most_common_tuple[1]}:{most_common_tuple[2]}:{most_common_tuple[3]}"
|
|
||||||
|
|
||||||
return {
|
|
||||||
"safe_crop": safe_crop,
|
|
||||||
"most_common": most_common,
|
|
||||||
"valid_crops_considered": len(valid_crops),
|
|
||||||
"raw_crops_count": total_frames
|
|
||||||
}
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print("Usage: python detect_crop.py <video_file>")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
file_path = sys.argv[1]
|
|
||||||
result = detect_crop(file_path)
|
|
||||||
print(json.dumps(result, indent=2))
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
def transcode_video(input_file, output_file, crop_param, hw_accel=False):
|
|
||||||
"""
|
|
||||||
Transcodes the video and applies cropping.
|
|
||||||
crop_param: string in the format "W:H:X:Y"
|
|
||||||
hw_accel: boolean, if true we use hardware acceleration (NVENC as an example)
|
|
||||||
"""
|
|
||||||
cmd = ['ffmpeg', '-y', '-i', input_file]
|
|
||||||
|
|
||||||
# We apply the crop filter
|
|
||||||
vf_param = f'crop={crop_param}'
|
|
||||||
|
|
||||||
if hw_accel:
|
|
||||||
# Example using NVIDIA NVENC.
|
|
||||||
# In a real Jellyfin environment, this would be constructed based on Jellyfin's profile.
|
|
||||||
cmd.extend([
|
|
||||||
'-c:v', 'h264_nvenc',
|
|
||||||
'-preset', 'fast',
|
|
||||||
'-vf', vf_param,
|
|
||||||
'-c:a', 'copy' # Keep audio as is
|
|
||||||
])
|
|
||||||
else:
|
|
||||||
# Software encoding fallback
|
|
||||||
cmd.extend([
|
|
||||||
'-c:v', 'libx264',
|
|
||||||
'-preset', 'fast',
|
|
||||||
'-crf', '23',
|
|
||||||
'-vf', vf_param,
|
|
||||||
'-c:a', 'copy'
|
|
||||||
])
|
|
||||||
|
|
||||||
cmd.append(output_file)
|
|
||||||
|
|
||||||
print(f"Running transcoding command: {' '.join(cmd)}")
|
|
||||||
|
|
||||||
# In a real scenario, this would stream to Jellyfin's output or write to the required segment files.
|
|
||||||
process = subprocess.Popen(cmd)
|
|
||||||
process.wait()
|
|
||||||
|
|
||||||
if process.returncode == 0:
|
|
||||||
print("Transcoding completed successfully.")
|
|
||||||
else:
|
|
||||||
print(f"Transcoding failed with code {process.returncode}")
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(sys.argv) < 4:
|
|
||||||
print("Usage: python transcode_crop.py <input_file> <output_file> <crop_param>")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
input_file = sys.argv[1]
|
|
||||||
output_file = sys.argv[2]
|
|
||||||
crop_param = sys.argv[3]
|
|
||||||
|
|
||||||
transcode_video(input_file, output_file, crop_param, hw_accel=False)
|
|
||||||
Reference in New Issue
Block a user