diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8b82132..85cf175 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,7 +4,6 @@
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
-
{
"name": "Python: Web",
"type": "python",
@@ -68,8 +67,7 @@
"request": "launch",
"program": "mkgui\\base\\_cli.py",
"console": "integratedTerminal",
- "args": [ "mkgui.app:mocking_bird"
- ]
+ "args": []
},
]
}
diff --git a/mkgui/app.py b/mkgui/app.py
index 8387a60..775f695 100644
--- a/mkgui/app.py
+++ b/mkgui/app.py
@@ -38,6 +38,9 @@ if os.path.isdir(VOC_MODELS_DIRT):
class Input(BaseModel):
+ message: str = Field(
+ ..., example="欢迎使用工具箱, 现已支持中文输入!", alias="文本内容"
+ )
local_audio_file: audio_input_selection = Field(
..., alias="输入语音(本地wav)",
description="选择本地语音文件."
@@ -56,9 +59,6 @@ class Input(BaseModel):
..., alias="语音编码模型",
description="选择语音编码模型文件(目前只支持HifiGan类型)."
)
- message: str = Field(
- ..., example="欢迎使用工具箱, 现已支持中文输入!", alias="输出文本内容"
- )
class AudioEntity(BaseModel):
content: bytes
@@ -72,7 +72,8 @@ class Output(BaseModel):
If this method is implmeneted, it will be used instead of the default Output UI renderer.
"""
src, result = self.__root__
- streamlit_app.subheader("Result Audio")
+
+ streamlit_app.subheader("Synthesized Audio")
streamlit_app.audio(result.content, format="audio/wav")
fig, ax = plt.subplots()
@@ -85,8 +86,8 @@ class Output(BaseModel):
streamlit_app.pyplot(fig)
-def mocking_bird(input: Input) -> Output:
- """欢迎使用MockingBird Web 2"""
+def main(input: Input) -> Output:
+ """synthesize(合成)"""
# load models
encoder.load_model(Path(input.encoder.value))
current_synt = Synthesizer(Path(input.synthesizer.value))
diff --git a/mkgui/base/_cli.py b/mkgui/base/_cli.py
index 937a839..036ee95 100644
--- a/mkgui/base/_cli.py
+++ b/mkgui/base/_cli.py
@@ -5,7 +5,7 @@ import typer
cli = typer.Typer()
@cli.command()
-def launch_ui(opyrator: str, port: int = typer.Option(8051, "--port", "-p")) -> None:
+def launch_ui(port: int = typer.Option(8051, "--port", "-p")) -> None:
"""Start a graphical UI server for the opyrator.
The UI is auto-generated from the input- and output-schema of the given function.
@@ -15,7 +15,7 @@ def launch_ui(opyrator: str, port: int = typer.Option(8051, "--port", "-p")) ->
sys.path.append(os.getcwd())
from mkgui.base.ui.streamlit_ui import launch_ui
- launch_ui(opyrator, port)
+ launch_ui(port)
if __name__ == "__main__":
cli()
\ No newline at end of file
diff --git a/mkgui/base/api/fastapi_app.py b/mkgui/base/api/fastapi_app.py
deleted file mode 100644
index 234b6c5..0000000
--- a/mkgui/base/api/fastapi_app.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from typing import Any, Dict
-
-from fastapi import FastAPI, status
-from fastapi.middleware.cors import CORSMiddleware
-from starlette.responses import RedirectResponse
-
-from mkgui.base import Opyrator
-from mkgui.base.api.fastapi_utils import patch_fastapi
-
-
-def launch_api(opyrator_path: str, port: int = 8501, host: str = "0.0.0.0") -> None:
- import uvicorn
-
- from mkgui.base import Opyrator
- from mkgui.base.api import create_api
-
- app = create_api(Opyrator(opyrator_path))
- uvicorn.run(app, host=host, port=port, log_level="info")
-
-
-def create_api(opyrator: Opyrator) -> FastAPI:
-
- title = opyrator.name
- if "opyrator" not in opyrator.name.lower():
- title += " - Opyrator"
-
- # TODO what about version?
- app = FastAPI(title=title, description=opyrator.description)
-
- patch_fastapi(app)
-
- app.add_middleware(
- CORSMiddleware,
- allow_origins=["*"],
- allow_credentials=True,
- allow_methods=["*"],
- allow_headers=["*"],
- )
-
- @app.post(
- "/call",
- operation_id="call",
- response_model=opyrator.output_type,
- # response_model_exclude_unset=True,
- summary="Execute the opyrator.",
- status_code=status.HTTP_200_OK,
- )
- def call(input: opyrator.input_type) -> Any: # type: ignore
- """Executes this opyrator."""
- return opyrator(input)
-
- @app.get(
- "/info",
- operation_id="info",
- response_model=Dict,
- # response_model_exclude_unset=True,
- summary="Get info metadata.",
- status_code=status.HTTP_200_OK,
- )
- def info() -> Any: # type: ignore
- """Returns informational metadata about this Opyrator."""
- return {}
-
- # Redirect to docs
- @app.get("/", include_in_schema=False)
- def root() -> Any:
- return RedirectResponse("./docs")
-
- return app
diff --git a/mkgui/base/core.py b/mkgui/base/core.py
index 069d352..fe7ed50 100644
--- a/mkgui/base/core.py
+++ b/mkgui/base/core.py
@@ -113,7 +113,7 @@ class Opyrator:
self.function = func
self._name = "Opyrator"
- self._description = ""
+ self._action = "Execute"
self._input_type = None
self._output_type = None
@@ -140,7 +140,7 @@ class Opyrator:
# Get description from function
doc_string = inspect.getdoc(self.function)
if doc_string:
- self._description = doc_string
+ self._action = doc_string
except Exception:
pass
elif hasattr(self.function, "__call__"):
@@ -155,19 +155,19 @@ class Opyrator:
pass
try:
- # Get description from
+ # Get action from
doc_string = inspect.getdoc(self.function.__call__) # type: ignore
if doc_string:
- self._description = doc_string
+ self._action = doc_string
if (
- not self._description
- or self._description == "Call self as a function."
+ not self._action
+ or self._action == "Call"
):
# Get docstring from class instead of __call__ function
doc_string = inspect.getdoc(self.function)
if doc_string:
- self._description = doc_string
+ self._action = doc_string
except Exception:
pass
else:
@@ -178,8 +178,8 @@ class Opyrator:
return self._name
@property
- def description(self) -> str:
- return self._description
+ def action(self) -> str:
+ return self._action
@property
def input_type(self) -> Any:
diff --git a/mkgui/base/ui/streamlit_ui.py b/mkgui/base/ui/streamlit_ui.py
index 52bdb4d..7401957 100644
--- a/mkgui/base/ui/streamlit_ui.py
+++ b/mkgui/base/ui/streamlit_ui.py
@@ -32,21 +32,20 @@ st.set_page_config(
page_icon="🧊",
layout="wide")
-with st.spinner("Loading MockingBird GUI. Please wait..."):
- opyrator = Opyrator("{opyrator_path}")
-
-render_streamlit_ui(opyrator, action="{action}")
+render_streamlit_ui()
"""
+# with st.spinner("Loading MockingBird GUI. Please wait..."):
+# opyrator = Opyrator("{opyrator_path}")
+
-def launch_ui(opyrator_path: str, port: int = 8501) -> None:
+def launch_ui(port: int = 8501) -> None:
with NamedTemporaryFile(
suffix=".py", mode="w", encoding="utf-8", delete=False
) as f:
- f.write(STREAMLIT_RUNNER_SNIPPET.format_map({'opyrator_path': opyrator_path, 'action': "Synthesize"}))
+ f.write(STREAMLIT_RUNNER_SNIPPET)
f.seek(0)
- # TODO: PYTHONPATH="$PYTHONPATH:/workspace/opyrator/src"
import subprocess
python_path = f'PYTHONPATH="$PYTHONPATH:{getcwd()}"'
@@ -801,30 +800,42 @@ class OutputUI:
streamlit.json(jsonable_encoder(output_data))
-def render_streamlit_ui(opyrator: Opyrator, action: str = "Execute") -> None:
- title = opyrator.name
+def getOpyrator(mode: str) -> Opyrator:
+ # if mode == None or mode.startswith('VC'):
+ # from mkgui.app_vc import vc
+ # return Opyrator(vc)
+ from mkgui.app import main
+ return Opyrator(main)
+
+def render_streamlit_ui() -> None:
# init
session_state = st.session_state
session_state.input_data = {}
+ session_state.mode = None
+
+ with st.spinner("Loading MockingBird GUI. Please wait..."):
+ session_state.mode = st.sidebar.selectbox(
+ '模式选择',
+ ("AI拟音", "VC拟音")
+ )
+ opyrator = getOpyrator(session_state.mode)
+ title = opyrator.name
col1, col2, _ = st.columns(3)
col2.title(title)
+ col2.markdown("欢迎使用MockingBird Web 2")
+
image = Image.open('.\\mkgui\\static\\mb.png')
col1.image(image)
- # Add custom css settings
- st.markdown(f"", unsafe_allow_html=True)
-
- if opyrator.description:
- st.markdown(opyrator.description)
-
- left, right = st.columns([0.3, 0.8])
- InputUI(session_state=session_state, input_class=opyrator.input_type).render_ui(left)
-
+ st.markdown("---")
+ left, right = st.columns([0.4, 0.6])
with left:
- execute_selected = st.button(action)
+ st.header("Control 控制")
+ InputUI(session_state=session_state, input_class=opyrator.input_type).render_ui(st)
+ execute_selected = st.button(opyrator.action)
if execute_selected:
with st.spinner("Executing operation. Please wait..."):
try:
@@ -838,18 +849,23 @@ def render_streamlit_ui(opyrator: Opyrator, action: str = "Execute") -> None:
else:
# st.success("Operation executed successfully.")
pass
- if st.button("Clear"):
- # Clear all state
- for key in st.session_state.keys():
- del st.session_state[key]
- session_state.input_data = {}
- st.experimental_rerun()
-
-
- if 'output_data' in session_state:
- OutputUI(
- session_state.output_data, session_state.latest_operation_input
- ).render_ui(right)
- # st.markdown("---")
+ with right:
+ st.header("Result 结果")
+ if 'output_data' in session_state:
+ OutputUI(
+ session_state.output_data, session_state.latest_operation_input
+ ).render_ui(st)
+ if st.button("Clear"):
+ # Clear all state
+ for key in st.session_state.keys():
+ del st.session_state[key]
+ session_state.input_data = {}
+ st.experimental_rerun()
+ else:
+ # placeholder
+ st.caption("请使用左侧控制板进行输入并运行获得结果")
+
+ # Add custom css settings
+ st.markdown(f"", unsafe_allow_html=True)
diff --git a/mkgui/base/ui/streamlit_utils.py b/mkgui/base/ui/streamlit_utils.py
index e8f15c6..beb6e65 100644
--- a/mkgui/base/ui/streamlit_utils.py
+++ b/mkgui/base/ui/streamlit_utils.py
@@ -4,6 +4,9 @@ div[data-testid="stBlock"] button {
margin-bottom: 20px !important;
border-color: #bfbfbf !important;
}
+section[data-testid="stSidebar"] div {
+ max-width: 10rem;
+}
pre code {
white-space: pre-wrap;
}