Spaces:
Sleeping
Sleeping
Update webui/app.py
Browse files- webui/app.py +32 -12
webui/app.py
CHANGED
|
@@ -130,7 +130,7 @@ def apply_experimental_preset(preset_name):
|
|
| 130 |
# Subtitle logic moved to subtitle_handler.py
|
| 131 |
|
| 132 |
|
| 133 |
-
def run_viral_cutter(input_source, project_name, url, video_file, segments, viral, themes, min_duration, max_duration, model, ai_backend, api_key, ai_model_name, chunk_size, workflow, face_model, face_mode, face_detect_interval,
|
| 134 |
face_filter_thresh, face_two_thresh, face_conf_thresh, face_dead_zone, focus_active_speaker, active_speaker_mar, active_speaker_score_diff, include_motion, active_speaker_motion_threshold, active_speaker_motion_sensitivity, active_speaker_decay,
|
| 135 |
use_custom_subs, font_name, font_size, font_color, highlight_color, outline_color, outline_thickness, shadow_color, shadow_size, is_bold, is_italic, is_uppercase, vertical_pos, alignment,
|
| 136 |
h_size, w_block, gap, mode, under, strike, border_s, remove_punc, video_quality, use_youtube_subs, translate_target):
|
|
@@ -203,6 +203,7 @@ def run_viral_cutter(input_source, project_name, url, video_file, segments, vira
|
|
| 203 |
cmd.extend(["--face-model", face_model])
|
| 204 |
cmd.extend(["--face-mode", face_mode])
|
| 205 |
if face_detect_interval: cmd.extend(["--face-detect-interval", str(face_detect_interval)])
|
|
|
|
| 206 |
|
| 207 |
# New Face Params
|
| 208 |
if face_filter_thresh is not None: cmd.extend(["--face-filter-threshold", str(face_filter_thresh)])
|
|
@@ -334,7 +335,7 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 334 |
with gr.Tab(i18n("Create New")):
|
| 335 |
with gr.Row():
|
| 336 |
with gr.Column(scale=1):
|
| 337 |
-
input_source = gr.Radio([(i18n("YouTube URL"), "YouTube URL"), (i18n("Existing Project"), "Existing Project"), (i18n("Upload Video"), "Upload Video")], label=i18n("Input Source"), value="Upload Video")
|
| 338 |
|
| 339 |
url_input = gr.Textbox(label=i18n("YouTube URL"), placeholder="https://www.youtube.com/watch?v=...", visible=False)
|
| 340 |
video_upload = gr.File(label=i18n("Upload Video"), file_count="single", file_types=["video"], visible=True)
|
|
@@ -348,9 +349,9 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 348 |
|
| 349 |
def on_source_change(source):
|
| 350 |
if source == "YouTube URL":
|
| 351 |
-
return gr.update(visible=
|
| 352 |
elif source == "Upload Video":
|
| 353 |
-
return gr.update(visible=
|
| 354 |
else:
|
| 355 |
# Load projects
|
| 356 |
projs = library.get_existing_projects()
|
|
@@ -367,7 +368,7 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 367 |
max_dur_input = gr.Number(label=i18n("Max Duration (s)"), value=90)
|
| 368 |
with gr.Column(scale=1):
|
| 369 |
with gr.Row():
|
| 370 |
-
ai_backend_input = gr.Dropdown(choices=[(i18n("Gemini"), "gemini"), (i18n("G4F"), "g4f"), (i18n("Local (GGUF)"), "local"), (i18n("Manual"), "manual")], label=i18n("AI Backend"), value="gemini", scale=2)
|
| 371 |
api_key_input = gr.Textbox(label=i18n("Gemini API Key"), type="password", scale=3)
|
| 372 |
|
| 373 |
# New Dynamic Inputs
|
|
@@ -389,16 +390,16 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 389 |
if backend == "gemini":
|
| 390 |
new_choices = GEMINI_MODELS
|
| 391 |
new_val = GEMINI_MODELS[1]
|
| 392 |
-
new_chunk =
|
| 393 |
elif backend == "g4f":
|
| 394 |
new_choices = G4F_MODELS
|
| 395 |
-
new_val = G4F_MODELS[
|
| 396 |
-
new_chunk =
|
| 397 |
elif backend == "local":
|
| 398 |
models = get_local_models()
|
| 399 |
new_choices = models if models else [i18n("No models found")]
|
| 400 |
new_val = new_choices[0]
|
| 401 |
-
new_chunk =
|
| 402 |
else: # Manual
|
| 403 |
pass
|
| 404 |
|
|
@@ -424,6 +425,7 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 424 |
with gr.Row():
|
| 425 |
face_mode_input = gr.Dropdown(choices=[(i18n("Auto"), "auto"), ("1", "1"), ("2", "2")], label=i18n("Face Mode"), value="auto")
|
| 426 |
face_detect_interval_input = gr.Textbox(label=i18n("Face Det. Interval"), value="0.17,1.0")
|
|
|
|
| 427 |
|
| 428 |
|
| 429 |
# Update listeners now that all components are defined
|
|
@@ -540,7 +542,25 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 540 |
function() {
|
| 541 |
var ta = document.querySelector('#logs_output textarea');
|
| 542 |
if(ta) {
|
| 543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 544 |
}
|
| 545 |
}
|
| 546 |
""")
|
|
@@ -550,7 +570,7 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 550 |
start_btn.click(run_viral_cutter, inputs=[
|
| 551 |
input_source, project_selector, url_input, video_upload, segments_input, viral_input, themes_input, min_dur_input, max_dur_input,
|
| 552 |
model_input, ai_backend_input, api_key_input, ai_model_input, chunk_size_input,
|
| 553 |
-
workflow_input, face_model_input, face_mode_input, face_detect_interval_input,
|
| 554 |
face_filter_thresh_input, face_two_thresh_input, face_conf_thresh_input, face_dead_zone_input, focus_active_speaker_input,
|
| 555 |
active_speaker_mar_input, active_speaker_score_diff_input, include_motion_input, active_speaker_motion_threshold_input, active_speaker_motion_sensitivity_input, active_speaker_decay_input,
|
| 556 |
use_custom_subs,
|
|
@@ -748,7 +768,7 @@ with gr.Blocks(title=i18n("ViralCutter WebUI"), theme=gr.themes.Default(primary_
|
|
| 748 |
{i18n('Apoie o projeto, qualquer valor é bem-vindo:')}
|
| 749 |
<a href='https://nubank.com.br/pagar/1ls6a4/0QpSSbWBSq' target='_blank'><strong>{i18n('Apoiar via PIX')}</strong></a>
|
| 750 |
<br>
|
| 751 |
-
{i18n('100% local • open source •
|
| 752 |
</p>
|
| 753 |
</div>
|
| 754 |
""")
|
|
|
|
| 130 |
# Subtitle logic moved to subtitle_handler.py
|
| 131 |
|
| 132 |
|
| 133 |
+
def run_viral_cutter(input_source, project_name, url, video_file, segments, viral, themes, min_duration, max_duration, model, ai_backend, api_key, ai_model_name, chunk_size, workflow, face_model, face_mode, face_detect_interval, no_face_mode,
|
| 134 |
face_filter_thresh, face_two_thresh, face_conf_thresh, face_dead_zone, focus_active_speaker, active_speaker_mar, active_speaker_score_diff, include_motion, active_speaker_motion_threshold, active_speaker_motion_sensitivity, active_speaker_decay,
|
| 135 |
use_custom_subs, font_name, font_size, font_color, highlight_color, outline_color, outline_thickness, shadow_color, shadow_size, is_bold, is_italic, is_uppercase, vertical_pos, alignment,
|
| 136 |
h_size, w_block, gap, mode, under, strike, border_s, remove_punc, video_quality, use_youtube_subs, translate_target):
|
|
|
|
| 203 |
cmd.extend(["--face-model", face_model])
|
| 204 |
cmd.extend(["--face-mode", face_mode])
|
| 205 |
if face_detect_interval: cmd.extend(["--face-detect-interval", str(face_detect_interval)])
|
| 206 |
+
if no_face_mode: cmd.extend(["--no-face-mode", no_face_mode])
|
| 207 |
|
| 208 |
# New Face Params
|
| 209 |
if face_filter_thresh is not None: cmd.extend(["--face-filter-threshold", str(face_filter_thresh)])
|
|
|
|
| 335 |
with gr.Tab(i18n("Create New")):
|
| 336 |
with gr.Row():
|
| 337 |
with gr.Column(scale=1):
|
| 338 |
+
input_source = gr.Radio([(i18n("YouTube URL | Off HF"), "YouTube URL"), (i18n("Existing Project"), "Existing Project"), (i18n("Upload Video"), "Upload Video")], label=i18n("Input Source"), value="Upload Video")
|
| 339 |
|
| 340 |
url_input = gr.Textbox(label=i18n("YouTube URL"), placeholder="https://www.youtube.com/watch?v=...", visible=False)
|
| 341 |
video_upload = gr.File(label=i18n("Upload Video"), file_count="single", file_types=["video"], visible=True)
|
|
|
|
| 349 |
|
| 350 |
def on_source_change(source):
|
| 351 |
if source == "YouTube URL":
|
| 352 |
+
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(value="Full")
|
| 353 |
elif source == "Upload Video":
|
| 354 |
+
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(value="Full")
|
| 355 |
else:
|
| 356 |
# Load projects
|
| 357 |
projs = library.get_existing_projects()
|
|
|
|
| 368 |
max_dur_input = gr.Number(label=i18n("Max Duration (s)"), value=90)
|
| 369 |
with gr.Column(scale=1):
|
| 370 |
with gr.Row():
|
| 371 |
+
ai_backend_input = gr.Dropdown(choices=[(i18n("Gemini"), "gemini"), (i18n("G4F"), "g4f"), (i18n("Local (GGUF) (Off HF)"), "local"), (i18n("Manual"), "manual")], label=i18n("AI Backend"), value="gemini", scale=2)
|
| 372 |
api_key_input = gr.Textbox(label=i18n("Gemini API Key"), type="password", scale=3)
|
| 373 |
|
| 374 |
# New Dynamic Inputs
|
|
|
|
| 390 |
if backend == "gemini":
|
| 391 |
new_choices = GEMINI_MODELS
|
| 392 |
new_val = GEMINI_MODELS[1]
|
| 393 |
+
new_chunk = 70000
|
| 394 |
elif backend == "g4f":
|
| 395 |
new_choices = G4F_MODELS
|
| 396 |
+
new_val = G4F_MODELS[5]
|
| 397 |
+
new_chunk = 70000
|
| 398 |
elif backend == "local":
|
| 399 |
models = get_local_models()
|
| 400 |
new_choices = models if models else [i18n("No models found")]
|
| 401 |
new_val = new_choices[0]
|
| 402 |
+
new_chunk = 30000
|
| 403 |
else: # Manual
|
| 404 |
pass
|
| 405 |
|
|
|
|
| 425 |
with gr.Row():
|
| 426 |
face_mode_input = gr.Dropdown(choices=[(i18n("Auto"), "auto"), ("1", "1"), ("2", "2")], label=i18n("Face Mode"), value="auto")
|
| 427 |
face_detect_interval_input = gr.Textbox(label=i18n("Face Det. Interval"), value="0.17,1.0")
|
| 428 |
+
no_face_mode_input = gr.Dropdown(choices=[(i18n("Padding (9:16)"), "padding"), (i18n("Zoom (Center)"), "zoom")], label=i18n("No Face Fallback"), value="zoom")
|
| 429 |
|
| 430 |
|
| 431 |
# Update listeners now that all components are defined
|
|
|
|
| 542 |
function() {
|
| 543 |
var ta = document.querySelector('#logs_output textarea');
|
| 544 |
if(ta) {
|
| 545 |
+
// Setup scroll listener once to track user intent
|
| 546 |
+
if (!ta._scrollerSetup) {
|
| 547 |
+
ta._isSticky = true; // Default to sticky
|
| 548 |
+
ta.addEventListener('scroll', function() {
|
| 549 |
+
var diff = ta.scrollHeight - ta.scrollTop - ta.clientHeight;
|
| 550 |
+
// If near bottom (<50px), enable sticky. Else disable.
|
| 551 |
+
if (diff <= 50) {
|
| 552 |
+
ta._isSticky = true;
|
| 553 |
+
} else {
|
| 554 |
+
ta._isSticky = false;
|
| 555 |
+
}
|
| 556 |
+
});
|
| 557 |
+
ta._scrollerSetup = true;
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
// Apply scroll only if sticky
|
| 561 |
+
if(ta._isSticky === undefined || ta._isSticky === true) {
|
| 562 |
+
ta.scrollTop = ta.scrollHeight;
|
| 563 |
+
}
|
| 564 |
}
|
| 565 |
}
|
| 566 |
""")
|
|
|
|
| 570 |
start_btn.click(run_viral_cutter, inputs=[
|
| 571 |
input_source, project_selector, url_input, video_upload, segments_input, viral_input, themes_input, min_dur_input, max_dur_input,
|
| 572 |
model_input, ai_backend_input, api_key_input, ai_model_input, chunk_size_input,
|
| 573 |
+
workflow_input, face_model_input, face_mode_input, face_detect_interval_input, no_face_mode_input,
|
| 574 |
face_filter_thresh_input, face_two_thresh_input, face_conf_thresh_input, face_dead_zone_input, focus_active_speaker_input,
|
| 575 |
active_speaker_mar_input, active_speaker_score_diff_input, include_motion_input, active_speaker_motion_threshold_input, active_speaker_motion_sensitivity_input, active_speaker_decay_input,
|
| 576 |
use_custom_subs,
|
|
|
|
| 768 |
{i18n('Apoie o projeto, qualquer valor é bem-vindo:')}
|
| 769 |
<a href='https://nubank.com.br/pagar/1ls6a4/0QpSSbWBSq' target='_blank'><strong>{i18n('Apoiar via PIX')}</strong></a>
|
| 770 |
<br>
|
| 771 |
+
{i18n('100% local • open source • no subscription required')}
|
| 772 |
</p>
|
| 773 |
</div>
|
| 774 |
""")
|