Fumiya Imazato Claude Opus 4.5 commited on
Commit
63ce202
·
1 Parent(s): b4886e5

Fix: restore gr.Blocks + WebRTC, add prevention checklist

Browse files

- Reverted from Stream.ui.launch() to gr.Blocks + WebRTC
- Fixed track_constraints structure with "video" key
- Enhanced CSS for footer hiding
- Added prevention checklist to TROUBLESHOOTING.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Files changed (2) hide show
  1. TROUBLESHOOTING.md +40 -0
  2. app.py +55 -8
TROUBLESHOOTING.md CHANGED
@@ -739,3 +739,43 @@ Dockerfile でビルド時に事前ダウンロード:
739
  ```dockerfile
740
  RUN python -c "from paddleocr import PaddleOCR; PaddleOCR(use_angle_cls=True, lang='japan')" || true
741
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  ```dockerfile
740
  RUN python -c "from paddleocr import PaddleOCR; PaddleOCR(use_angle_cls=True, lang='japan')" || true
741
  ```
742
+
743
+ ## 再発防止チェックリスト
744
+
745
+ ### 必須確認事項(コード変更時に必ずチェック)
746
+
747
+ 1. **外カメラ設定**
748
+ - `track_constraints` に `"facingMode": {"exact": "environment"}` が含まれているか
749
+ - `track_constraints` の構造が正しいか(`{"video": {...}}` 形式)
750
+
751
+ 2. **フッター非表示**
752
+ - `CUSTOM_CSS` に `footer { display: none !important; }` が含まれているか
753
+ - `gr.Blocks()` に `css=CUSTOM_CSS` が渡されているか
754
+
755
+ 3. **ボタンラベル**
756
+ - `button_labels` に日本語ではなく英語("Start", "Stop")が設定されているか
757
+ - "録音" という文字列がコード内に存在しないか
758
+
759
+ 4. **Stream.ui.launch() は使わない**
760
+ - `Stream.ui.launch()` はデフォルトUIを使うため、カスタマイズ不可
761
+ - 必ず `gr.Blocks()` + `WebRTC` コンポーネントを使用すること
762
+
763
+ ### track_constraints の正しい形式
764
+
765
+ ```python
766
+ # 正しい形式
767
+ TRACK_CONSTRAINTS = {
768
+ "video": {
769
+ "width": {"ideal": 1280},
770
+ "height": {"ideal": 720},
771
+ "frameRate": {"ideal": 15},
772
+ "facingMode": {"exact": "environment"},
773
+ }
774
+ }
775
+
776
+ # 間違った形式(videoキーがない)
777
+ TRACK_CONSTRAINTS = {
778
+ "width": {"ideal": 1280},
779
+ "facingMode": {"exact": "environment"},
780
+ }
781
+ ```
app.py CHANGED
@@ -5,7 +5,8 @@ dokoCame - Real-time video location identification service
5
  from typing import Optional
6
  import os
7
  import numpy as np
8
- from fastrtc import Stream, get_cloudflare_turn_credentials
 
9
  import cv2
10
 
11
  from config.settings import settings
@@ -153,20 +154,66 @@ def process_video_frame(frame: np.ndarray) -> np.ndarray:
153
  return frame
154
 
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  if __name__ == "__main__":
157
  if not settings.validate():
158
  print("Warning: GEMINI_API_KEY required for VLM")
159
 
160
  rtc_config = get_cloudflare_turn_credentials if os.getenv("HF_TOKEN") else None
161
 
162
- stream = Stream(
163
- handler=process_video_frame,
164
- modality="video",
165
- mode="send-receive",
166
- rtc_configuration=rtc_config,
167
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- stream.ui.launch(
170
  server_name="0.0.0.0",
171
  server_port=7860,
172
  share=False,
 
5
  from typing import Optional
6
  import os
7
  import numpy as np
8
+ import gradio as gr
9
+ from fastrtc import WebRTC, get_cloudflare_turn_credentials
10
  import cv2
11
 
12
  from config.settings import settings
 
154
  return frame
155
 
156
 
157
+ # ========== 設定 ==========
158
+ # 外カメラ強制
159
+ TRACK_CONSTRAINTS = {
160
+ "video": {
161
+ "width": {"ideal": 1280},
162
+ "height": {"ideal": 720},
163
+ "frameRate": {"ideal": 15},
164
+ "facingMode": {"exact": "environment"},
165
+ }
166
+ }
167
+
168
+ # フッター非表示CSS
169
+ CUSTOM_CSS = """
170
+ .gradio-container { max-width: 100% !important; padding: 0 !important; }
171
+ footer { display: none !important; visibility: hidden !important; height: 0 !important; }
172
+ .built-with { display: none !important; }
173
+ .svelte-1rjryqp { display: none !important; }
174
+ #footer { display: none !important; }
175
+ .footer { display: none !important; }
176
+ .gr-footer { display: none !important; }
177
+ [class*="footer"] { display: none !important; }
178
+ """
179
+
180
+
181
+ # ========== メイン ==========
182
  if __name__ == "__main__":
183
  if not settings.validate():
184
  print("Warning: GEMINI_API_KEY required for VLM")
185
 
186
  rtc_config = get_cloudflare_turn_credentials if os.getenv("HF_TOKEN") else None
187
 
188
+ with gr.Blocks(
189
+ title="dokoCame",
190
+ css=CUSTOM_CSS,
191
+ theme=gr.themes.Default(),
192
+ ) as demo:
193
+ gr.Markdown("# dokoCame")
194
+
195
+ webrtc = WebRTC(
196
+ label="Camera",
197
+ mode="send-receive",
198
+ modality="video",
199
+ track_constraints=TRACK_CONSTRAINTS,
200
+ rtc_configuration=rtc_config,
201
+ icon_button_color="#4CAF50",
202
+ button_labels={
203
+ "start": "Start",
204
+ "stop": "Stop",
205
+ "waiting": "...",
206
+ },
207
+ )
208
+
209
+ webrtc.stream(
210
+ fn=process_video_frame,
211
+ inputs=[webrtc],
212
+ outputs=[webrtc],
213
+ time_limit=None,
214
+ )
215
 
216
+ demo.launch(
217
  server_name="0.0.0.0",
218
  server_port=7860,
219
  share=False,