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()
|