Update app-backup.py
Browse files- app-backup.py +159 -170
app-backup.py
CHANGED
@@ -31,12 +31,10 @@ from einops import rearrange
|
|
31 |
from scipy.io import wavfile
|
32 |
from transformers import pipeline
|
33 |
|
34 |
-
# ๋น๋์ค ๋ฐฐ๊ฒฝ์ ๊ฑฐ ๊ด๋ จ import
|
35 |
# ๋น๋์ค ๋ฐฐ๊ฒฝ์ ๊ฑฐ ๊ด๋ จ import
|
36 |
from transformers import AutoModelForImageSegmentation
|
37 |
from torchvision import transforms
|
38 |
|
39 |
-
|
40 |
# โโ moviepy import โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
41 |
try:
|
42 |
from moviepy.editor import (
|
@@ -148,8 +146,8 @@ from concurrent.futures import ThreadPoolExecutor
|
|
148 |
|
149 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
150 |
|
151 |
-
|
152 |
-
|
153 |
|
154 |
# ํ๊ฒฝ ๋ณ์ ์ค์ ์ผ๋ก torch.load ์ฒดํฌ ์ฐํ (์์ ํด๊ฒฐ์ฑ
)
|
155 |
os.environ["TRANSFORMERS_ALLOW_UNSAFE_DESERIALIZATION"] = "1"
|
@@ -206,8 +204,11 @@ TRANSLATOR = None
|
|
206 |
# API URLs
|
207 |
TEXT2IMG_API_URL = "http://211.233.58.201:7896"
|
208 |
VIDEO_API_URL = "http://211.233.58.201:7875"
|
209 |
-
|
210 |
|
|
|
|
|
|
|
211 |
# Image size presets
|
212 |
IMAGE_PRESETS = {
|
213 |
"์ปค์คํ
": {"width": 1024, "height": 1024},
|
@@ -988,140 +989,82 @@ def merge_videos_with_audio(video_files, audio_file, audio_mode, audio_volume, o
|
|
988 |
traceback.print_exc()
|
989 |
return None, f"โ ์ค๋ฅ ๋ฐ์: {str(e)}"
|
990 |
|
991 |
-
|
992 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
993 |
"""์ด๋ฏธ์ง์ ์ค๋์ค๋ก ์๋ฐํ ์ ๋๋ฉ์ด์
์์ฑ"""
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
if driving_audio is None:
|
998 |
-
return None, None, "์ค๋์ค ํ์ผ์ ์
๋ก๋ํด์ฃผ์ธ์."
|
999 |
|
1000 |
try:
|
1001 |
-
|
1002 |
-
|
1003 |
-
|
1004 |
-
# ์ด๋ฏธ์ง ์ฒ๋ฆฌ - filepath๋ก ๋ฐ์ผ๋ฏ๋ก ์ง์ ์ฌ์ฉ
|
1005 |
-
portrait_path = portrait_image
|
1006 |
-
|
1007 |
-
# ์ด๋ฏธ์ง๊ฐ ์ค์ ๋ก ์กด์ฌํ๋์ง ํ์ธ
|
1008 |
-
if not os.path.exists(portrait_path):
|
1009 |
-
# ๋ง์ฝ numpy array๋ PIL ์ด๋ฏธ์ง๋ก ์๋ค๋ฉด ์ ์ฅ
|
1010 |
-
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as fp:
|
1011 |
-
temp_portrait_path = fp.name
|
1012 |
-
if isinstance(portrait_image, np.ndarray):
|
1013 |
-
Image.fromarray(portrait_image).save(temp_portrait_path)
|
1014 |
-
elif isinstance(portrait_image, Image.Image):
|
1015 |
-
portrait_image.save(temp_portrait_path)
|
1016 |
-
else:
|
1017 |
-
return None, None, "โ ์ด๋ฏธ์ง ํ์์ ์ธ์ํ ์ ์์ต๋๋ค."
|
1018 |
-
portrait_path = temp_portrait_path
|
1019 |
-
|
1020 |
-
# ์ค๋์ค ๊ฒฝ๋ก ํ์ธ
|
1021 |
-
audio_path = driving_audio
|
1022 |
-
|
1023 |
-
# ๊ฒฝ๋ก ๋ก๊น
|
1024 |
-
logging.info(f"Portrait path: {portrait_path}")
|
1025 |
-
logging.info(f"Audio path: {audio_path}")
|
1026 |
-
logging.info(f"Guidance Scale: {guidance_scale}")
|
1027 |
-
logging.info(f"Inference Steps: {inference_steps}")
|
1028 |
|
1029 |
-
|
1030 |
-
|
1031 |
-
return None, None, f"โ ์ด๋ฏธ์ง ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค: {portrait_path}"
|
1032 |
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
|
|
|
|
1039 |
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
audio_path, # ์ง์ ๊ฒฝ๋ก ์ ๋ฌ
|
1058 |
-
float(guidance_scale),
|
1059 |
-
float(inference_steps),
|
1060 |
-
api_name="/generate_animation"
|
1061 |
-
)
|
1062 |
-
|
1063 |
-
# ์ฑ๊ณตํ๋ฉด ๋ฃจํ ์ข
๋ฃ
|
1064 |
-
break
|
1065 |
-
|
1066 |
-
except (httpx.ConnectTimeout, httpx.TimeoutException) as e:
|
1067 |
-
logging.warning(f"์ฐ๊ฒฐ ํ์์์ (์๋ {attempt + 1}/{max_retries}): {str(e)}")
|
1068 |
-
if attempt < max_retries - 1:
|
1069 |
-
logging.info(f"{retry_delay}์ด ํ ์ฌ์๋...")
|
1070 |
-
time.sleep(retry_delay)
|
1071 |
else:
|
1072 |
-
|
1073 |
-
|
1074 |
-
# ๋ค๋ฅธ ์์ธ๋ ์ฆ์ ์ฒ๋ฆฌ
|
1075 |
-
raise e
|
1076 |
-
|
1077 |
-
# ์์ ํ์ผ ์ญ์ (์๋ ๊ฒฝ์ฐ)
|
1078 |
-
if 'temp_portrait_path' in locals() and os.path.exists(temp_portrait_path):
|
1079 |
-
os.unlink(temp_portrait_path)
|
1080 |
-
|
1081 |
-
# ๊ฒฐ๊ณผ ์ฒ๋ฆฌ
|
1082 |
-
if result and len(result) >= 2:
|
1083 |
-
animation_result = result[0]
|
1084 |
-
comparison_result = result[1]
|
1085 |
-
|
1086 |
-
# ๊ฒฐ๊ณผ๊ฐ dict์ธ์ง ์ง์ ๊ฒฝ๋ก์ธ์ง ํ์ธ
|
1087 |
-
if isinstance(animation_result, dict):
|
1088 |
-
animation_video = animation_result.get("video")
|
1089 |
-
else:
|
1090 |
-
animation_video = animation_result
|
1091 |
-
|
1092 |
-
if isinstance(comparison_result, dict):
|
1093 |
-
comparison_video = comparison_result.get("video")
|
1094 |
else:
|
1095 |
-
|
|
|
|
|
|
|
|
|
|
|
1096 |
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
else:
|
1101 |
-
logging.warning(f"Animation video not found or invalid: {animation_video}")
|
1102 |
-
|
1103 |
-
if comparison_video and os.path.exists(str(comparison_video)):
|
1104 |
-
logging.info(f"Comparison video created: {comparison_video}")
|
1105 |
else:
|
1106 |
-
|
1107 |
-
|
1108 |
-
return animation_video, comparison_video, "โ
์๋ฐํ ์ ๋๋ฉ์ด์
์์ฑ ์๋ฃ!"
|
1109 |
else:
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
except httpx.ConnectTimeout:
|
1114 |
-
logging.error("Connection timeout to API server")
|
1115 |
-
return None, None, "โ API ์๋ฒ ์ฐ๊ฒฐ ์๊ฐ ์ด๊ณผ. ์๋ฒ๊ฐ ์๋ตํ์ง ์์ต๋๋ค."
|
1116 |
-
except httpx.TimeoutException:
|
1117 |
-
logging.error("Request timeout")
|
1118 |
-
return None, None, "โ ์์ฒญ ์๊ฐ ์ด๊ณผ. ์๋ฒ ์ฒ๋ฆฌ ์๊ฐ์ด ๋๋ฌด ๊น๋๋ค."
|
1119 |
except Exception as e:
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
# CSS
|
1126 |
css = """
|
1127 |
:root {
|
@@ -1147,13 +1090,16 @@ css = """
|
|
1147 |
padding: 20px !important;
|
1148 |
margin-bottom: 20px !important;
|
1149 |
}
|
1150 |
-
#generate-btn, #video-btn, #outpaint-btn, #preview-btn, #audio-btn, #bg-remove-btn, #merge-btn, #avatar-btn {
|
1151 |
background: linear-gradient(135deg, #ff9a9e, #fad0c4) !important;
|
1152 |
font-size: 1.1rem !important;
|
1153 |
padding: 12px 24px !important;
|
1154 |
margin-top: 10px !important;
|
1155 |
width: 100% !important;
|
1156 |
}
|
|
|
|
|
|
|
1157 |
.tabitem {
|
1158 |
min-height: 700px !important;
|
1159 |
}
|
@@ -1345,8 +1291,7 @@ with demo:
|
|
1345 |
interactive=False
|
1346 |
)
|
1347 |
|
1348 |
-
|
1349 |
-
# ๋ค ๋ฒ์งธ ํญ: ๋น๋์ค ํธ์ง ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ด ์์
|
1350 |
with gr.Tab("๋น๋์ค ํธ์ง", elem_classes="tabitem"):
|
1351 |
with gr.Row(equal_height=True):
|
1352 |
# ์
๋ ฅ ์ปฌ๋ผ
|
@@ -1380,7 +1325,6 @@ with demo:
|
|
1380 |
- ์ต์์ ๊ฒฐ๊ณผ๋ฅผ ์ํด ๊ฐ์ ํฌ๊ธฐ์ ๋น๋์ค๋ฅผ ์ฌ์ฉํ์ธ์
|
1381 |
""")
|
1382 |
|
1383 |
-
|
1384 |
with gr.Group(elem_classes="panel-box"):
|
1385 |
gr.Markdown("### ๐ต ์ค๋์ค ์ค์ (์ ํ)")
|
1386 |
|
@@ -1553,73 +1497,114 @@ with demo:
|
|
1553 |
**์ฐธ๊ณ **: GPU ์ ํ์ผ๋ก ํ ๋ฒ์ ์ฝ 200ํ๋ ์๊น์ง ์ฒ๋ฆฌ ๊ฐ๋ฅํฉ๋๋ค.
|
1554 |
๊ธด ๋น๋์ค๋ ์์ ์กฐ๊ฐ์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ์ธ์.
|
1555 |
""")
|
1556 |
-
|
1557 |
-
# ์ฌ์ฏ ๋ฒ์งธ ํญ: ์ด๋ฏธ์งto์๋ฐํ
|
1558 |
with gr.Tab("์ด๋ฏธ์งto์๋ฐํ", elem_classes="tabitem"):
|
1559 |
with gr.Row(equal_height=True):
|
1560 |
# ์
๋ ฅ ์ปฌ๋ผ
|
1561 |
with gr.Column(scale=1):
|
1562 |
with gr.Group(elem_classes="panel-box"):
|
1563 |
-
gr.Markdown("###
|
|
|
|
|
1564 |
|
1565 |
-
|
1566 |
-
|
|
|
|
|
|
|
|
|
|
|
1567 |
type="filepath",
|
1568 |
-
|
1569 |
)
|
1570 |
|
1571 |
-
with gr.Group(elem_classes="panel-box"):
|
1572 |
-
gr.Markdown("### ๐ต ์ค๋์ค ์
๋ก๋")
|
1573 |
-
|
1574 |
avatar_audio = gr.Audio(
|
1575 |
-
label="
|
1576 |
type="filepath",
|
1577 |
-
|
1578 |
)
|
1579 |
-
|
1580 |
with gr.Group(elem_classes="panel-box"):
|
1581 |
gr.Markdown("### โ๏ธ ์์ฑ ์ค์ ")
|
1582 |
|
1583 |
-
|
1584 |
minimum=1.0,
|
1585 |
-
maximum=
|
1586 |
-
value=
|
1587 |
step=0.1,
|
1588 |
label="๊ฐ์ด๋์ค ์ค์ผ์ผ",
|
1589 |
-
info="
|
1590 |
)
|
1591 |
|
1592 |
-
|
1593 |
minimum=5,
|
1594 |
maximum=30,
|
1595 |
-
value=
|
1596 |
step=1,
|
1597 |
label="์ถ๋ก ์คํ
",
|
1598 |
-
info="
|
1599 |
)
|
1600 |
|
1601 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1602 |
|
1603 |
# ์ถ๋ ฅ ์ปฌ๋ผ
|
1604 |
with gr.Column(scale=1):
|
1605 |
with gr.Group(elem_classes="panel-box"):
|
1606 |
-
gr.Markdown("###
|
|
|
|
|
|
|
|
|
|
|
1607 |
|
1608 |
-
|
1609 |
-
|
1610 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1611 |
|
1612 |
gr.Markdown("""
|
1613 |
-
### โน๏ธ ์ฌ์ฉ
|
1614 |
-
|
1615 |
-
|
1616 |
-
|
1617 |
-
|
|
|
|
|
|
|
|
|
|
|
1618 |
|
1619 |
**ํ**:
|
1620 |
-
-
|
1621 |
- ์ค๋์ค์ ์์ฑ์ด ๋ช
ํํ ์๋ก ๋ฆฝ์ฑํฌ๊ฐ ์ ํํฉ๋๋ค
|
1622 |
-
- ๊ฐ์ด๋์ค๋ฅผ ๋์ด๋ฉด ์์ง์์ด ๊ฐํด์ง๋๋ค
|
1623 |
""")
|
1624 |
|
1625 |
# ๋ชจ๋ธ ๋ก๋ ํจ์ ์คํ
|
@@ -1671,7 +1656,6 @@ with demo:
|
|
1671 |
)
|
1672 |
|
1673 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ๋ค ๋ฒ์งธ ํญ (๋น๋์ค ํธ์ง)
|
1674 |
-
|
1675 |
def toggle_original_volume(mode):
|
1676 |
return gr.update(visible=(mode == "๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฎค์ง"))
|
1677 |
|
@@ -1681,12 +1665,12 @@ with demo:
|
|
1681 |
outputs=[original_audio_volume]
|
1682 |
)
|
1683 |
|
1684 |
-
|
1685 |
merge_videos_btn.click(
|
1686 |
merge_videos_with_audio,
|
1687 |
inputs=[video_files, audio_file, audio_mode, audio_volume, original_audio_volume, output_fps],
|
1688 |
outputs=[merged_video, merge_status]
|
1689 |
-
)
|
|
|
1690 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ๋ค์ฏ ๋ฒ์งธ ํญ (๋น๋์ค ๋ฐฐ๊ฒฝ์ ๊ฑฐ/ํฉ์ฑ)
|
1691 |
def update_bg_visibility(bg_type):
|
1692 |
if bg_type == "์์":
|
@@ -1710,12 +1694,17 @@ with demo:
|
|
1710 |
fps_slider, video_handling_radio, fast_mode_checkbox, max_workers_slider],
|
1711 |
outputs=[stream_image, output_bg_video, time_textbox]
|
1712 |
)
|
1713 |
-
|
1714 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ์ฌ์ฏ ๋ฒ์งธ ํญ (์ด๋ฏธ์งto์๋ฐํ)
|
1715 |
-
|
|
|
|
|
|
|
|
|
|
|
1716 |
generate_avatar_animation,
|
1717 |
-
inputs=[
|
1718 |
-
outputs=[avatar_result, avatar_comparison,
|
1719 |
)
|
1720 |
|
1721 |
# ๋ฐ๋ชจ ๋ก๋ ์ ์คํ
|
@@ -1729,4 +1718,4 @@ if __name__ == "__main__":
|
|
1729 |
except:
|
1730 |
pass
|
1731 |
|
1732 |
-
demo.launch()
|
|
|
31 |
from scipy.io import wavfile
|
32 |
from transformers import pipeline
|
33 |
|
|
|
34 |
# ๋น๋์ค ๋ฐฐ๊ฒฝ์ ๊ฑฐ ๊ด๋ จ import
|
35 |
from transformers import AutoModelForImageSegmentation
|
36 |
from torchvision import transforms
|
37 |
|
|
|
38 |
# โโ moviepy import โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
39 |
try:
|
40 |
from moviepy.editor import (
|
|
|
146 |
|
147 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
148 |
|
149 |
+
import httpx
|
150 |
+
from datetime import datetime
|
151 |
|
152 |
# ํ๊ฒฝ ๋ณ์ ์ค์ ์ผ๋ก torch.load ์ฒดํฌ ์ฐํ (์์ ํด๊ฒฐ์ฑ
)
|
153 |
os.environ["TRANSFORMERS_ALLOW_UNSAFE_DESERIALIZATION"] = "1"
|
|
|
204 |
# API URLs
|
205 |
TEXT2IMG_API_URL = "http://211.233.58.201:7896"
|
206 |
VIDEO_API_URL = "http://211.233.58.201:7875"
|
207 |
+
ANIM_API_URL = os.getenv("ANIM_API_URL", "http://211.233.58.201:7862/")
|
208 |
|
209 |
+
# HTTP ํ์์์ ์ค์ - ๊ดํธ ์์
|
210 |
+
ANIM_TIMEOUT = httpx.Timeout(connect=30.0, read=120.0, write=120.0, pool=30.0)
|
211 |
+
|
212 |
# Image size presets
|
213 |
IMAGE_PRESETS = {
|
214 |
"์ปค์คํ
": {"width": 1024, "height": 1024},
|
|
|
989 |
traceback.print_exc()
|
990 |
return None, f"โ ์ค๋ฅ ๋ฐ์: {str(e)}"
|
991 |
|
992 |
+
def test_anim_api_connection():
|
993 |
+
"""์ ๋๋ฉ์ด์
์๋ฒ ์ฐ๊ฒฐ ํ
์คํธ"""
|
994 |
+
now = datetime.now().strftime("%H:%M:%S")
|
995 |
+
try:
|
996 |
+
resp = httpx.get(f"{ANIM_API_URL.rstrip('/')}/healthz", timeout=ANIM_TIMEOUT)
|
997 |
+
ready = resp.json().get("ready", False)
|
998 |
+
msg = f"[{now}] ์ ๋๋ฉ์ด์
์๋ฒ ์ฐ๊ฒฐ ์ฑ๊ณต โ
(ready={ready})"
|
999 |
+
logging.info(msg)
|
1000 |
+
return True, msg
|
1001 |
+
except Exception as e:
|
1002 |
+
msg = f"[{now}] ์ ๋๋ฉ์ด์
์๋ฒ ์ฐ๊ฒฐ ์คํจ โ : {e}"
|
1003 |
+
logging.error(msg)
|
1004 |
+
return False, msg
|
1005 |
+
|
1006 |
+
def generate_avatar_animation(image, audio, guidance_scale, steps, progress=gr.Progress()):
|
1007 |
"""์ด๋ฏธ์ง์ ์ค๋์ค๋ก ์๋ฐํ ์ ๋๋ฉ์ด์
์์ฑ"""
|
1008 |
+
start = datetime.now().strftime("%H:%M:%S")
|
1009 |
+
logs = [f"[{start}] ์์ฒญ ์์"]
|
|
|
|
|
|
|
1010 |
|
1011 |
try:
|
1012 |
+
if image is None or audio is None:
|
1013 |
+
raise ValueError("์ด๋ฏธ์ง์ ์ค๋์ค๋ฅผ ๋ชจ๋ ์
๋ก๋ํ์ธ์.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1014 |
|
1015 |
+
progress(0.05, desc="ํ์ผ ์ค๋น")
|
1016 |
+
client = Client(ANIM_API_URL)
|
|
|
1017 |
|
1018 |
+
progress(0.15, desc="์๋ฒ ํธ์ถ ์คโฆ (์ ๋ถ ์์ ๊ฐ๋ฅ)")
|
1019 |
+
result = client.predict(
|
1020 |
+
image_path=handle_file(image),
|
1021 |
+
audio_path=handle_file(audio),
|
1022 |
+
guidance_scale=guidance_scale,
|
1023 |
+
steps=steps,
|
1024 |
+
api_name="/generate_animation"
|
1025 |
+
)
|
1026 |
|
1027 |
+
progress(0.95, desc="๊ฒฐ๊ณผ ์ ๋ฆฌ")
|
1028 |
+
|
1029 |
+
# ๊ฒฐ๊ณผ ์ฒ๋ฆฌ - dict ํํ ์ฒ๋ฆฌ ์ถ๊ฐ
|
1030 |
+
def extract_video_path(obj):
|
1031 |
+
"""๋น๋์ค ๊ฐ์ฒด์์ ๊ฒฝ๋ก ์ถ์ถ"""
|
1032 |
+
if isinstance(obj, str):
|
1033 |
+
return obj
|
1034 |
+
elif isinstance(obj, dict):
|
1035 |
+
# Gradio์ FileData dict ์ฒ๋ฆฌ
|
1036 |
+
if 'video' in obj:
|
1037 |
+
return obj['video'] # {'video': '๊ฒฝ๋ก', 'subtitles': None} ํํ ์ฒ๋ฆฌ
|
1038 |
+
elif 'path' in obj:
|
1039 |
+
return obj['path']
|
1040 |
+
elif 'url' in obj:
|
1041 |
+
return obj['url']
|
1042 |
+
elif 'name' in obj:
|
1043 |
+
return obj['name']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1044 |
else:
|
1045 |
+
logging.warning(f"Unexpected dict structure: {obj.keys()}")
|
1046 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1047 |
else:
|
1048 |
+
logging.warning(f"Unexpected type: {type(obj)}")
|
1049 |
+
return None
|
1050 |
+
|
1051 |
+
if isinstance(result, (list, tuple)) and len(result) >= 2:
|
1052 |
+
anim_path = extract_video_path(result[0])
|
1053 |
+
comp_path = extract_video_path(result[1])
|
1054 |
|
1055 |
+
if anim_path and comp_path:
|
1056 |
+
logs.append(f"[{datetime.now().strftime('%H:%M:%S')}] ์ฑ๊ณต")
|
1057 |
+
return anim_path, comp_path, "\n".join(logs)
|
|
|
|
|
|
|
|
|
|
|
1058 |
else:
|
1059 |
+
raise RuntimeError(f"๋น๋์ค ๊ฒฝ๋ก ์ถ์ถ ์คํจ: {result}")
|
|
|
|
|
1060 |
else:
|
1061 |
+
raise RuntimeError(f"์์์น ๋ชปํ ๋ฐํ ํ์: {type(result)}")
|
1062 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1063 |
except Exception as e:
|
1064 |
+
logs.append(f"[{datetime.now().strftime('%H:%M:%S')}] ์ค๋ฅ: {e}")
|
1065 |
+
logging.error(f"Avatar animation generation error: {e}", exc_info=True)
|
1066 |
+
return None, None, "\n".join(logs)
|
1067 |
+
|
|
|
1068 |
# CSS
|
1069 |
css = """
|
1070 |
:root {
|
|
|
1090 |
padding: 20px !important;
|
1091 |
margin-bottom: 20px !important;
|
1092 |
}
|
1093 |
+
#generate-btn, #video-btn, #outpaint-btn, #preview-btn, #audio-btn, #bg-remove-btn, #merge-btn, #avatar-btn, #test-connection-btn {
|
1094 |
background: linear-gradient(135deg, #ff9a9e, #fad0c4) !important;
|
1095 |
font-size: 1.1rem !important;
|
1096 |
padding: 12px 24px !important;
|
1097 |
margin-top: 10px !important;
|
1098 |
width: 100% !important;
|
1099 |
}
|
1100 |
+
#avatar-btn, #test-connection-btn {
|
1101 |
+
background: linear-gradient(135deg, #667eea, #764ba2) !important;
|
1102 |
+
}
|
1103 |
.tabitem {
|
1104 |
min-height: 700px !important;
|
1105 |
}
|
|
|
1291 |
interactive=False
|
1292 |
)
|
1293 |
|
1294 |
+
# ๋ค ๋ฒ์งธ ํญ: ๋น๋์ค ํธ์ง
|
|
|
1295 |
with gr.Tab("๋น๋์ค ํธ์ง", elem_classes="tabitem"):
|
1296 |
with gr.Row(equal_height=True):
|
1297 |
# ์
๋ ฅ ์ปฌ๋ผ
|
|
|
1325 |
- ์ต์์ ๊ฒฐ๊ณผ๋ฅผ ์ํด ๊ฐ์ ํฌ๊ธฐ์ ๋น๋์ค๋ฅผ ์ฌ์ฉํ์ธ์
|
1326 |
""")
|
1327 |
|
|
|
1328 |
with gr.Group(elem_classes="panel-box"):
|
1329 |
gr.Markdown("### ๐ต ์ค๋์ค ์ค์ (์ ํ)")
|
1330 |
|
|
|
1497 |
**์ฐธ๊ณ **: GPU ์ ํ์ผ๋ก ํ ๋ฒ์ ์ฝ 200ํ๋ ์๊น์ง ์ฒ๋ฆฌ ๊ฐ๋ฅํฉ๋๋ค.
|
1498 |
๊ธด ๋น๋์ค๋ ์์ ์กฐ๊ฐ์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ์ธ์.
|
1499 |
""")
|
1500 |
+
|
1501 |
+
# ์ฌ์ฏ ๋ฒ์งธ ํญ: ์ด๋ฏธ์งto์๋ฐํ (์ค๋ณต ์ ๊ฑฐํ๊ณ ํ๋๋ง ์ ์ง)
|
1502 |
with gr.Tab("์ด๋ฏธ์งto์๋ฐํ", elem_classes="tabitem"):
|
1503 |
with gr.Row(equal_height=True):
|
1504 |
# ์
๋ ฅ ์ปฌ๋ผ
|
1505 |
with gr.Column(scale=1):
|
1506 |
with gr.Group(elem_classes="panel-box"):
|
1507 |
+
gr.Markdown("### ๐ญ ์๋ฐํ ์ ๋๋ฉ์ด์
์์ฑ")
|
1508 |
+
gr.Markdown("""
|
1509 |
+
ํฌํธ๋ ์ดํธ ์ด๋ฏธ์ง์ ์ค๋์ค๋ฅผ ์
๋ก๋ํ๋ฉด ๋งํ๋ ์๋ฐํ ์ ๋๋ฉ์ด์
์ ์์ฑํฉ๋๋ค.
|
1510 |
|
1511 |
+
**๊ถ์ฅ ์ฌํญ**:
|
1512 |
+
- ์ด๋ฏธ์ง: ์ ๋ฉด์ ๋ณด๊ณ ์๋ ์ผ๊ตด ์ฌ์ง
|
1513 |
+
- ์ค๋์ค: ๋ช
ํํ ์์ฑ์ด ๋ด๊ธด ์ค๋์ค ํ์ผ
|
1514 |
+
""")
|
1515 |
+
|
1516 |
+
avatar_image = gr.Image(
|
1517 |
+
label="ํฌํธ๋ ์ดํธ ์ด๋ฏธ์ง",
|
1518 |
type="filepath",
|
1519 |
+
elem_classes="panel-box"
|
1520 |
)
|
1521 |
|
|
|
|
|
|
|
1522 |
avatar_audio = gr.Audio(
|
1523 |
+
label="๋๋ผ์ด๋น ์ค๋์ค",
|
1524 |
type="filepath",
|
1525 |
+
elem_classes="panel-box"
|
1526 |
)
|
1527 |
+
|
1528 |
with gr.Group(elem_classes="panel-box"):
|
1529 |
gr.Markdown("### โ๏ธ ์์ฑ ์ค์ ")
|
1530 |
|
1531 |
+
guidance_scale = gr.Slider(
|
1532 |
minimum=1.0,
|
1533 |
+
maximum=10.0,
|
1534 |
+
value=3.0,
|
1535 |
step=0.1,
|
1536 |
label="๊ฐ์ด๋์ค ์ค์ผ์ผ",
|
1537 |
+
info="๋์์๋ก ์ค๋์ค์ ๋ ์ถฉ์คํ ์์ง์ ์์ฑ"
|
1538 |
)
|
1539 |
|
1540 |
+
inference_steps = gr.Slider(
|
1541 |
minimum=5,
|
1542 |
maximum=30,
|
1543 |
+
value=10,
|
1544 |
step=1,
|
1545 |
label="์ถ๋ก ์คํ
",
|
1546 |
+
info="๋์์๋ก ํ์ง์ด ์ข์์ง์ง๋ง ์์ฑ ์๊ฐ์ด ์ฆ๊ฐ"
|
1547 |
)
|
1548 |
|
1549 |
+
# ์๋ฒ ์ํ ์ฒดํฌ
|
1550 |
+
with gr.Row():
|
1551 |
+
test_connection_btn = gr.Button(
|
1552 |
+
"๐ ์๋ฒ ์ฐ๊ฒฐ ํ
์คํธ",
|
1553 |
+
elem_id="test-connection-btn",
|
1554 |
+
scale=1
|
1555 |
+
)
|
1556 |
+
|
1557 |
+
anim_status = gr.Textbox(
|
1558 |
+
label="์๋ฒ ์ํ",
|
1559 |
+
interactive=False,
|
1560 |
+
elem_classes="panel-box"
|
1561 |
+
)
|
1562 |
+
|
1563 |
+
generate_avatar_btn = gr.Button(
|
1564 |
+
"๐ฌ ์๋ฐํ ์์ฑ",
|
1565 |
+
variant="primary",
|
1566 |
+
elem_id="avatar-btn"
|
1567 |
+
)
|
1568 |
|
1569 |
# ์ถ๋ ฅ ์ปฌ๋ผ
|
1570 |
with gr.Column(scale=1):
|
1571 |
with gr.Group(elem_classes="panel-box"):
|
1572 |
+
gr.Markdown("### ๐ญ ์์ฑ ๊ฒฐ๊ณผ")
|
1573 |
+
|
1574 |
+
avatar_result = gr.Video(
|
1575 |
+
label="์ ๋๋ฉ์ด์
๊ฒฐ๊ณผ",
|
1576 |
+
elem_classes="panel-box"
|
1577 |
+
)
|
1578 |
|
1579 |
+
avatar_comparison = gr.Video(
|
1580 |
+
label="์๋ณธ ๋๋น ๊ฒฐ๊ณผ (Side-by-Side)",
|
1581 |
+
elem_classes="panel-box"
|
1582 |
+
)
|
1583 |
+
|
1584 |
+
with gr.Accordion("์คํ ๋ก๊ทธ", open=False):
|
1585 |
+
avatar_logs = gr.Textbox(
|
1586 |
+
label="๋ก๊ทธ",
|
1587 |
+
lines=10,
|
1588 |
+
max_lines=20,
|
1589 |
+
interactive=False,
|
1590 |
+
elem_classes="panel-box"
|
1591 |
+
)
|
1592 |
|
1593 |
gr.Markdown("""
|
1594 |
+
### โน๏ธ ์ฌ์ฉ ์๋ด
|
1595 |
+
|
1596 |
+
1. **ํฌํธ๋ ์ดํธ ์ด๋ฏธ์ง ์
๋ก๋**: ์ ๋ฉด์ ๋ณด๊ณ ์๋ ์ ๋ช
ํ ์ผ๊ตด ์ฌ์ง
|
1597 |
+
2. **์ค๋์ค ์
๋ก๋**: ์ ๋๋ฉ์ด์
์ ์ฌ์ฉํ ์์ฑ ํ์ผ
|
1598 |
+
3. **์ค์ ์กฐ์ **: ๊ฐ์ด๋์ค ์ค์ผ์ผ๊ณผ ์ถ๋ก ์คํ
์กฐ์
|
1599 |
+
4. **์์ฑ ์์**: '์๋ฐํ ์์ฑ' ๋ฒํผ ํด๋ฆญ
|
1600 |
+
|
1601 |
+
**์ฒ๋ฆฌ ์๊ฐ**:
|
1602 |
+
- ์ผ๋ฐ์ ์ผ๋ก 2-5๋ถ ์์
|
1603 |
+
- ๊ธด ์ค๋์ค์ผ์๋ก ์ฒ๋ฆฌ ์๊ฐ ์ฆ๊ฐ
|
1604 |
|
1605 |
**ํ**:
|
1606 |
+
- ๋ฐฐ๊ฒฝ์ด ๋จ์ํ ์ด๋ฏธ์ง๊ฐ ๋ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํฉ๋๋ค
|
1607 |
- ์ค๋์ค์ ์์ฑ์ด ๋ช
ํํ ์๋ก ๋ฆฝ์ฑํฌ๊ฐ ์ ํํฉ๋๋ค
|
|
|
1608 |
""")
|
1609 |
|
1610 |
# ๋ชจ๋ธ ๋ก๋ ํจ์ ์คํ
|
|
|
1656 |
)
|
1657 |
|
1658 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ๋ค ๋ฒ์งธ ํญ (๋น๋์ค ํธ์ง)
|
|
|
1659 |
def toggle_original_volume(mode):
|
1660 |
return gr.update(visible=(mode == "๋ฐฑ๊ทธ๋ผ์ด๋ ๋ฎค์ง"))
|
1661 |
|
|
|
1665 |
outputs=[original_audio_volume]
|
1666 |
)
|
1667 |
|
|
|
1668 |
merge_videos_btn.click(
|
1669 |
merge_videos_with_audio,
|
1670 |
inputs=[video_files, audio_file, audio_mode, audio_volume, original_audio_volume, output_fps],
|
1671 |
outputs=[merged_video, merge_status]
|
1672 |
+
)
|
1673 |
+
|
1674 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ๋ค์ฏ ๋ฒ์งธ ํญ (๋น๋์ค ๋ฐฐ๊ฒฝ์ ๊ฑฐ/ํฉ์ฑ)
|
1675 |
def update_bg_visibility(bg_type):
|
1676 |
if bg_type == "์์":
|
|
|
1694 |
fps_slider, video_handling_radio, fast_mode_checkbox, max_workers_slider],
|
1695 |
outputs=[stream_image, output_bg_video, time_textbox]
|
1696 |
)
|
1697 |
+
|
1698 |
# ์ด๋ฒคํธ ์ฐ๊ฒฐ - ์ฌ์ฏ ๋ฒ์งธ ํญ (์ด๋ฏธ์งto์๋ฐํ)
|
1699 |
+
test_connection_btn.click(
|
1700 |
+
test_anim_api_connection,
|
1701 |
+
outputs=[anim_status, anim_status]
|
1702 |
+
)
|
1703 |
+
|
1704 |
+
generate_avatar_btn.click(
|
1705 |
generate_avatar_animation,
|
1706 |
+
inputs=[avatar_image, avatar_audio, guidance_scale, inference_steps],
|
1707 |
+
outputs=[avatar_result, avatar_comparison, avatar_logs]
|
1708 |
)
|
1709 |
|
1710 |
# ๋ฐ๋ชจ ๋ก๋ ์ ์คํ
|
|
|
1718 |
except:
|
1719 |
pass
|
1720 |
|
1721 |
+
demo.launch()
|