DranikKartofelniy's picture
Upload 2 files
23bca14 verified
Raw
History Blame Contribute Delete
5.38 kB
import gradio as gr
import os
import shutil
import subprocess
import zipfile
import tempfile
from pathlib import Path
def compress_video(input_path, output_path, compression_level):
"""
Сжимает видео используя ffmpeg и CRF.
compression_level (1-3):
1 = Легкое сжатие (Высокое качество, CRF 23)
2 = Среднее сжатие (Баланс, CRF 28)
3 = Сильное сжатие (Низкое качество, CRF 35)
"""
# Настройки в зависимости от уровня слайдера
if compression_level == 1:
crf = "23" # Стандартное качество
preset = "medium"
elif compression_level == 2:
crf = "28" # Хорошее сжатие
preset = "faster"
else: # level 3
crf = "35" # Сильное сжатие (могут быть артефакты)
preset = "veryfast"
cmd = [
"ffmpeg",
"-y", # Перезаписать без вопросов
"-i", str(input_path),
"-c:v", "libx264",
"-crf", crf,
"-preset", preset,
"-c:a", "aac", # Сжимаем аудио тоже
"-b:a", "128k",
str(output_path)
]
try:
# Запускаем ffmpeg, подавляем лишний вывод
subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return True
except subprocess.CalledProcessError:
print(f"Error converting {input_path}")
return False
def process_archive(zip_file, compression_level):
if zip_file is None:
return None
# Создаем временные папки для работы
temp_dir = tempfile.mkdtemp()
input_dir = os.path.join(temp_dir, "input")
output_dir = os.path.join(temp_dir, "output")
os.makedirs(input_dir, exist_ok=True)
os.makedirs(output_dir, exist_ok=True)
try:
# 1. Распаковка архива
print("Распаковка архива...")
with zipfile.ZipFile(zip_file.name, 'r') as zip_ref:
zip_ref.extractall(input_dir)
# 2. Обход файлов и конвертация
video_extensions = {'.mp4', '.mov', '.avi', '.mkv', '.flv', '.wmv', '.webm'}
file_count = 0
for root, _, files in os.walk(input_dir):
for file_name in files:
if file_name.startswith("._") or file_name == ".DS_Store":
continue
input_path = Path(root) / file_name
# Сохраняем структуру папок
relative_path = os.path.relpath(root, input_dir)
output_subdir = os.path.join(output_dir, relative_path)
os.makedirs(output_subdir, exist_ok=True)
output_path = Path(output_subdir) / file_name
# Проверяем расширение
if input_path.suffix.lower() in video_extensions:
print(f"Сжимаю: {file_name} (Уровень {compression_level})")
# Меняем расширение на mp4 для единообразия, или оставляем как есть
# Для надежности лучше выводить в mp4, так как кодек libx264
output_path = output_path.with_suffix(".mp4")
success = compress_video(input_path, output_path, compression_level)
if not success:
# Если сбой, просто копируем оригинал
shutil.copy2(input_path, output_path)
else:
# Если не видео, просто копируем файл
shutil.copy2(input_path, output_path)
file_count += 1
# 3. Запаковка результата
print("Создание итогового архива...")
output_zip_path = os.path.join(temp_dir, "compressed_videos")
shutil.make_archive(output_zip_path, 'zip', output_dir)
return output_zip_path + ".zip"
finally:
# Очистка (удаляем временные распакованные папки, но возвращаем путь к зипу)
# shutil.rmtree(temp_dir) # Gradio само почистит temp файлы, но лучше оставить пока отдаем файл
pass
# Интерфейс Gradio
with gr.Interface(
fn=process_archive,
inputs=[
gr.File(label="Загрузите ZIP архив с видео"),
gr.Slider(minimum=1, maximum=3, step=1, value=2, label="Степень сжатия (1=Качество, 3=Маленький размер)")
],
outputs=gr.File(label="Скачать сжатый архив"),
title="Video Compressor",
description="Загрузите архив с видео. Скрипт найдет все видео, сожмет их и вернет архив с сохранением структуры папок."
) as demo:
pass
if __name__ == "__main__":
demo.launch()