Add mobile microphone HTTPS hints and Permissions-Policy header.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -289,11 +289,28 @@ PWA_HEAD = """
|
||||
return;
|
||||
}
|
||||
btn.style.display = "inline-flex";
|
||||
|
||||
// 非 HTTPS 时标记页面,用于显示麦克风提示
|
||||
if (!isSecure()) {
|
||||
document.documentElement.classList.add("insecure-context");
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
"""
|
||||
|
||||
MIC_HINT_HTML = """
|
||||
<div class="mic-hint">
|
||||
<strong>📱 手机 / 平板录音说明</strong>
|
||||
<ul>
|
||||
<li><strong>HTTPS 域名</strong>访问才能使用麦克风(HTTP 内网 IP 仅支持上传文件)</li>
|
||||
<li>iOS 请用 <strong>Safari</strong> 打开,微信内置浏览器通常无法录音</li>
|
||||
<li>首次使用请允许浏览器的「麦克风」权限</li>
|
||||
<li>穿透方案见 <code>PWA_NPS.md</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
"""
|
||||
|
||||
INSTALL_APP_BUTTON_HTML = """
|
||||
<button id="pwa-install-btn" class="pwa-install-btn" type="button" title="安装到手机/平板/电脑桌面">
|
||||
<img src="/pwa/icons/install.svg" alt="" class="pwa-install-icon" width="28" height="28"/>
|
||||
@@ -719,6 +736,31 @@ gradio-app,
|
||||
}
|
||||
|
||||
footer { visibility: hidden; }
|
||||
|
||||
/* 手机端麦克风提示(HTTP 下强制显示) */
|
||||
.mic-hint {
|
||||
display: none;
|
||||
background: #1e3a5f !important;
|
||||
border: 1px solid #3b82f6 !important;
|
||||
border-radius: 10px !important;
|
||||
padding: 12px 16px !important;
|
||||
margin: 8px 0 14px 0 !important;
|
||||
color: #dbeafe !important;
|
||||
font-size: 0.9rem !important;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
.mic-hint strong { color: #ffffff !important; }
|
||||
.mic-hint ul { margin: 8px 0 0 0 !important; padding-left: 20px !important; }
|
||||
.mic-hint code {
|
||||
background: #0f172a !important;
|
||||
color: #93c5fd !important;
|
||||
padding: 2px 6px !important;
|
||||
border-radius: 4px !important;
|
||||
}
|
||||
@media (max-width: 1024px) {
|
||||
.mic-hint { display: block; }
|
||||
}
|
||||
html.insecure-context .mic-hint { display: block !important; }
|
||||
"""
|
||||
|
||||
|
||||
@@ -843,6 +885,7 @@ def build_app() -> gr.Blocks:
|
||||
with gr.Tabs():
|
||||
# ---- Tab 1: 音色锁定 ----
|
||||
with gr.Tab("🎙️ 音色锁定"):
|
||||
gr.HTML(MIC_HINT_HTML)
|
||||
gr.HTML(
|
||||
f'<div class="hint-box">'
|
||||
f'上传 <strong>10-30 秒</strong> 干净人声样本,系统将提取 Speaker Embedding '
|
||||
@@ -873,6 +916,7 @@ def build_app() -> gr.Blocks:
|
||||
|
||||
# ---- Tab 2: 分步操作 ----
|
||||
with gr.Tab("🔧 分步流水线"):
|
||||
gr.HTML(MIC_HINT_HTML)
|
||||
with gr.Row(elem_classes=["pipeline-steps"]):
|
||||
with gr.Column(scale=1):
|
||||
gr.Markdown("### Step 1 · 音频极速识别")
|
||||
@@ -911,6 +955,7 @@ def build_app() -> gr.Blocks:
|
||||
|
||||
# ---- Tab 3: 一键生产 ----
|
||||
with gr.Tab("🚀 一键生产"):
|
||||
gr.HTML(MIC_HINT_HTML)
|
||||
gr.Markdown(
|
||||
"上传碎碎念录音,系统自动完成 **识别 → 润色 → 合成** 全流程。"
|
||||
)
|
||||
@@ -953,6 +998,13 @@ def create_fastapi_app():
|
||||
|
||||
fastapi_app = FastAPI(title="Trading Studio", docs_url=None, redoc_url=None)
|
||||
|
||||
@fastapi_app.middleware("http")
|
||||
async def add_media_permissions(request, call_next):
|
||||
"""允许浏览器在 HTTPS 下请求麦克风(配合云反代使用)。"""
|
||||
response = await call_next(request)
|
||||
response.headers["Permissions-Policy"] = "microphone=(self), camera=(self)"
|
||||
return response
|
||||
|
||||
if PWA_DIR.is_dir():
|
||||
fastapi_app.mount("/pwa", StaticFiles(directory=str(PWA_DIR)), name="pwa")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user