Spaces:
Sleeping
Sleeping
File size: 5,152 Bytes
7c204f4 73f6066 ea25738 7c204f4 ea25738 7c204f4 ea25738 7c204f4 73f6066 7c204f4 73f6066 ea25738 73f6066 7c204f4 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 ea25738 73f6066 7c204f4 73f6066 7c204f4 ea25738 7c204f4 ea25738 73f6066 ea25738 7c204f4 ea25738 73f6066 7c204f4 73f6066 7c204f4 ea25738 73f6066 7c204f4 73f6066 ea25738 7c204f4 ea25738 7c204f4 |
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 |
import gradio as gr
import ffmpeg
import os
import tempfile
import re
import shutil
def sanitize_filename(name):
name = os.path.splitext(os.path.basename(name))[0]
return re.sub(r'[^一-龥\w\-_.]', '_', name)
def compress_video(file, resize_mode, resize_value, mute,
audio_codec, audio_bitrate, audio_rate, audio_channels,
video_codec, video_bitrate, framerate, pix_fmt):
if not file:
return None, "ファイルが選択されていません"
input_path = file.name
safe_name = sanitize_filename(input_path)
SAVE_DIR = os.path.join(os.getcwd(), "compressed_videos")
os.makedirs(SAVE_DIR, exist_ok=True)
output_path = os.path.join(SAVE_DIR, f"{safe_name}_compressed.mp4")
try:
probe = ffmpeg.probe(input_path)
video_stream = next((s for s in probe['streams'] if s['codec_type'] == 'video'), None)
if not video_stream:
return None, "映像ストリームが見つかりません"
width = int(video_stream['width'])
height = int(video_stream['height'])
# リサイズ設定
resize_args = {}
if resize_mode == "パーセンテージ":
try:
percent = float(resize_value.strip('%')) / 100.0
assert 0 < percent <= 1
new_width = int(width * percent)
new_height = int(height * percent)
resize_args = {'vf': f'scale={new_width}:{new_height}'}
except Exception:
return None, "リサイズ値が無効です。例: 80%"
elif resize_mode == "ピクセル指定":
match = re.match(r"(\d+)[xX](\d+)", resize_value)
if not match:
return None, "リサイズ値が無効です。例: 1280x720"
new_width, new_height = map(int, match.groups())
resize_args = {'vf': f'scale={new_width}:{new_height}'}
# 音声設定
if mute:
audio_args = {'an': True}
else:
audio_args = {}
if audio_codec: audio_args['c:a'] = audio_codec
if audio_bitrate: audio_args['b:a'] = audio_bitrate
if audio_rate: audio_args['ar'] = audio_rate
if audio_channels: audio_args['ac'] = audio_channels
# 映像設定
video_args = {
'c:v': video_codec,
'crf': 18,
'preset': 'slow',
'r': framerate,
'pix_fmt': pix_fmt
}
if video_bitrate:
video_args['b:v'] = video_bitrate
stream = ffmpeg.input(input_path)
stream = ffmpeg.output(
stream,
output_path,
movflags='+faststart',
**resize_args,
**audio_args,
**video_args
)
ffmpeg.run(stream, overwrite_output=True)
return (output_path, None) if os.path.exists(output_path) else (None, "圧縮に失敗しました")
except Exception as e:
return None, f"エラーが発生しました: {str(e)}"
with gr.Blocks() as demo:
gr.Markdown("## 🎬 高画質を維持した動画圧縮ツール (カスタム設定付き)")
with gr.Row():
with gr.Column():
video_input = gr.File(label="動画ファイルを選択", file_types=[".mp4", ".mov", ".mkv", ".avi"])
resize_mode = gr.Radio(choices=["パーセンテージ", "ピクセル指定"], value="パーセンテージ", label="リサイズ方法")
resize_value = gr.Textbox(label="リサイズ値(例: 80% または 1280x720)", value="100%")
mute = gr.Checkbox(label="音声を消す(ミュート)", value=False)
gr.Markdown("### 音声設定")
audio_codec = gr.Textbox(label="音声コーデック (-c:a)", value="aac")
audio_bitrate = gr.Textbox(label="音声ビットレート (-b:a)", value="128k")
audio_rate = gr.Textbox(label="サンプリングレート (-ar)", value="44100")
audio_channels = gr.Textbox(label="チャンネル数 (-ac)", value="2")
gr.Markdown("### 映像設定")
video_codec = gr.Textbox(label="映像コーデック (-c:v)", value="libx264")
video_bitrate = gr.Textbox(label="映像ビットレート (-b:v、省略可)", value="")
framerate = gr.Textbox(label="フレームレート (-r)", value="30")
pix_fmt = gr.Textbox(label="ピクセルフォーマット (-pix_fmt)", value="yuv420p")
compress_btn = gr.Button("圧縮開始")
with gr.Column():
result_file = gr.File(label="圧縮された動画ファイル(ダウンロード)")
error_output = gr.Textbox(label="エラーメッセージ", lines=2)
compress_btn.click(
compress_video,
inputs=[video_input, resize_mode, resize_value, mute,
audio_codec, audio_bitrate, audio_rate, audio_channels,
video_codec, video_bitrate, framerate, pix_fmt],
outputs=[result_file, error_output]
)
if __name__ == "__main__":
demo.launch()
|