Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| Hugging Face Spaces 版本 - LiveKit 实时音视频对话 | |
| """ | |
| import gradio as gr | |
| import os | |
| def main(): | |
| # 获取 Hugging Face Space 的配置 | |
| space_id = os.getenv('SPACE_ID', 'unknown') | |
| with gr.Blocks( | |
| title="LiveKit 实时音视频对话", | |
| css=""" | |
| /* 简单清理样式,避免滚动条 */ | |
| html, body { | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| overflow: hidden !important; | |
| } | |
| /* 隐藏 Gradio 默认内容区域 */ | |
| .gradio-container { | |
| position: relative !important; | |
| overflow: hidden !important; | |
| } | |
| /* iframe 使用固定定位填满整个视口 */ | |
| #fullscreen-iframe { | |
| position: fixed !important; | |
| top: 0 !important; | |
| left: 0 !important; | |
| right: 0 !important; | |
| bottom: 0 !important; | |
| width: 100vw !important; | |
| height: 100vh !important; | |
| border: none !important; | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| z-index: 9999 !important; | |
| } | |
| """, | |
| head=""" | |
| <script> | |
| // 动态调整 iframe 以适配 Hugging Face Spaces | |
| document.addEventListener('DOMContentLoaded', function() { | |
| document.documentElement.style.overflow = 'hidden'; | |
| document.body.style.overflow = 'hidden'; | |
| function adjustIframe() { | |
| const iframe = document.querySelector('#fullscreen-iframe'); | |
| if (!iframe) return; | |
| // 查找 Hugging Face 顶部导航栏 | |
| const hfHeader = document.querySelector('header'); | |
| const gradioContainer = document.querySelector('.gradio-container'); | |
| let topOffset = 0; | |
| // 计算顶部偏移量 | |
| if (hfHeader) { | |
| topOffset = hfHeader.offsetHeight; | |
| console.log('🔍 检测到 HF 导航栏高度:', topOffset + 'px'); | |
| } else if (gradioContainer) { | |
| const rect = gradioContainer.getBoundingClientRect(); | |
| topOffset = rect.top; | |
| console.log('🔍 使用 Gradio 容器顶部偏移:', topOffset + 'px'); | |
| } | |
| // 设置 iframe 位置和大小,避开顶部导航 | |
| iframe.style.top = topOffset + 'px'; | |
| iframe.style.height = 'calc(100vh - ' + topOffset + 'px)'; | |
| console.log('✅ iframe 已调整 - 顶部偏移:', topOffset + 'px', '高度: calc(100vh - ' + topOffset + 'px)'); | |
| } | |
| // 多次尝试调整 | |
| setTimeout(adjustIframe, 50); | |
| setTimeout(adjustIframe, 200); | |
| setTimeout(adjustIframe, 500); | |
| setTimeout(adjustIframe, 1000); | |
| setTimeout(adjustIframe, 2000); | |
| // 监听窗口大小变化 | |
| window.addEventListener('resize', adjustIframe); | |
| console.log('✅ Hugging Face Spaces iframe 自适应已启动'); | |
| }); | |
| // 模式切换功能(通过键盘) | |
| document.addEventListener('keydown', function(e) { | |
| const iframe = document.querySelector('#fullscreen-iframe'); | |
| if (!iframe) return; | |
| // 数字键 0 - 音频模式 | |
| if (e.key === '0') { | |
| iframe.src = 'https://openbmb.github.io/MiniCPM-o-Demo/'; | |
| console.log('切换到音频模式'); | |
| } | |
| // 数字键 1 - 视频模式 | |
| else if (e.key === '1') { | |
| iframe.src = 'https://openbmb.github.io/MiniCPM-o-Demo/'; | |
| console.log('切换到视频模式'); | |
| } | |
| // 数字键 1 - 测试模式 | |
| else if (e.key === '3') { | |
| iframe.src = 'https://openbmb.github.io/MiniCPM-o-Demo/'; | |
| console.log('切换到视频模式'); | |
| } | |
| // R 键 - 刷新 | |
| else if (e.key === 'r' || e.key === 'R') { | |
| iframe.src = iframe.src; | |
| console.log('刷新 iframe'); | |
| } | |
| }); | |
| </script> | |
| """ | |
| ) as demo: | |
| # 全屏 iframe,使用 fixed 定位填满可用空间 | |
| gr.HTML(f""" | |
| <iframe | |
| id="fullscreen-iframe" | |
| src="https://openbmb.github.io/MiniCPM-o-Demo/" | |
| allowfullscreen | |
| allow="camera; microphone; autoplay; encrypted-media; fullscreen; display-capture; geolocation" | |
| title="LiveKit 实时音视频对话" | |
| onload="console.log('🎙️ LiveKit 应用在 Hugging Face 中加载完成');" | |
| onerror="console.error('❌ LiveKit 应用加载失败');"> | |
| </iframe> | |
| <!-- 隐藏的信息面板,按 I 键显示 --> | |
| <div id="info-panel" style="position: fixed; top: 10px; left: 10px; background: rgba(0,0,0,0.8); color: white; padding: 15px; border-radius: 10px; font-size: 12px; z-index: 999999; display: none;"> | |
| <h4 style="margin: 0 0 10px 0;">🎙️ LiveKit 实时音视频对话</h4> | |
| <p style="margin: 5px 0;">🏠 Hugging Face Space: {space_id}</p> | |
| <p style="margin: 5px 0;">🌐 嵌入应用: minicpm-omni.openbmb.cn/</p> | |
| <p style="margin: 5px 0;">⌨️ 快捷键:</p> | |
| <p style="margin: 2px 0 2px 20px;">• 0 - 音频模式</p> | |
| <p style="margin: 2px 0 2px 20px;">• 1 - 视频模式</p> | |
| <p style="margin: 2px 0 2px 20px;">• R - 刷新应用</p> | |
| <p style="margin: 2px 0 2px 20px;">• I - 显示/隐藏此面板</p> | |
| </div> | |
| <script> | |
| // I 键显示/隐藏信息面板 | |
| document.addEventListener('keydown', function(e) {{ | |
| if (e.key === 'i' || e.key === 'I') {{ | |
| const panel = document.querySelector('#info-panel'); | |
| if (panel) {{ | |
| panel.style.display = panel.style.display === 'none' ? 'block' : 'none'; | |
| }} | |
| }} | |
| }}); | |
| </script> | |
| """, show_label=False) | |
| return demo | |
| if __name__ == "__main__": | |
| demo = main() | |
| print("🎙️ LiveKit Hugging Face Spaces 版本") | |
| print("=" * 50) | |
| print("🌐 嵌入应用: https://35.226.63.1:8008/") | |
| print("🚀 部署平台: Hugging Face Spaces") | |
| print("📱 访问地址: http://localhost:7860") | |
| print("⌨️ 快捷键: 0(音频) 1(视频) R(刷新) I(信息)") | |
| print("=" * 50) | |
| # Hugging Face Spaces 部署配置 | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| show_error=True, | |
| # Hugging Face Spaces 优化配置 | |
| ) | |