Fumiya Imazato Claude Opus 4.5 commited on
Commit
251cf10
·
1 Parent(s): 933e052

Fix: Default rear camera with retry + improve UI instructions

Browse files

- Add retry logic for rear camera initialization
- Add gr.Blocks(js=...) for auto rear camera on page load
- Update label to clarify: "capture photo first, then analyze"
- Update usage instructions
- Record issues in 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 +57 -0
  2. app.py +52 -8
TROUBLESHOOTING.md CHANGED
@@ -266,3 +266,60 @@ async () => {
266
 
267
  switch_camera_btn.click(fn=None, js=switch_camera_js)
268
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
  switch_camera_btn.click(fn=None, js=switch_camera_js)
268
  ```
269
+
270
+ ## gr.Image streaming=False で画像がサーバーに送信されない
271
+
272
+ ### 問題
273
+ - 解析ボタンを押しても「カメラを起動してください」表示
274
+ - Container ログにデバッグ出力なし
275
+ - `frame=None` がサーバーに渡されている
276
+
277
+ ### 原因
278
+ - `gr.Image(sources=["webcam"], streaming=False)` では、カメラUI内の**撮影ボタン**を押して静止画をキャプチャしないと画像がセットされない
279
+ - カメラプレビューは表示されるが、ユーザーが明示的に撮影しないと `None` のまま
280
+
281
+ ### 解決策
282
+ UIの説明を改善して、ユーザーに操作手順を明示:
283
+ ```
284
+ 1. カメラUI内の撮影ボタンで写真を撮る
285
+ 2. 解析ボタンを押す
286
+ ```
287
+
288
+ ### ラベルの改善
289
+ ```python
290
+ webcam = gr.Image(
291
+ sources=["webcam"],
292
+ streaming=False,
293
+ label="📷 カメラで撮影してから解析ボタンを押してください",
294
+ )
295
+ ```
296
+
297
+ ## デフォルト外カメラが適用されない
298
+
299
+ ### 問題
300
+ - `gr.Blocks(js=camera_js)` を設定したが、カメラが内カメラのまま
301
+
302
+ ### 原因
303
+ - ページ読み込み時にカメラがまだ起動していない
304
+ - タイミングの問題で `video.srcObject` が `null`
305
+
306
+ ### 解決策
307
+ リトライロジック付きのJavaScriptを使用:
308
+ ```javascript
309
+ const initRearCamera = async () => {
310
+ await new Promise(r => setTimeout(r, 2000));
311
+
312
+ const video = document.querySelector('video');
313
+ if (!video || !video.srcObject) {
314
+ setTimeout(initRearCamera, 1000); // リトライ
315
+ return;
316
+ }
317
+
318
+ // 外カメラに切り替え
319
+ const stream = await navigator.mediaDevices.getUserMedia({
320
+ video: { facingMode: { ideal: 'environment' } }
321
+ });
322
+ video.srcObject = stream;
323
+ };
324
+ initRearCamera();
325
+ ```
app.py CHANGED
@@ -195,12 +195,54 @@ def reset_state():
195
  def create_ui():
196
  """Gradio UIを作成"""
197
 
198
- # カメラ状態管理
199
- camera_state = {"facing": "environment"} # environment=外カメ, user=内カメ
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
 
201
  with gr.Blocks(
202
  title="どこカメ - リアルタイム位置特定",
203
  theme=gr.themes.Soft(),
 
204
  ) as demo:
205
  gr.Markdown(
206
  """
@@ -215,13 +257,13 @@ def create_ui():
215
  webcam = gr.Image(
216
  sources=["webcam"],
217
  streaming=False,
218
- label="カメラ映像",
219
  mirror_webcam=False,
220
  )
221
 
222
  with gr.Row():
223
  # 解析ボタン
224
- analyze_btn = gr.Button("📸 解析する", variant="primary", size="lg")
225
  # カメラ切り替えボタン
226
  switch_camera_btn = gr.Button("🔄 内/外カメラ切替", variant="secondary")
227
 
@@ -311,14 +353,16 @@ def create_ui():
311
  """
312
  ---
313
  ### 使い方
314
- 1. カメラを許可して起動
315
- 2. **「内/外カメラ切替」**ボタンカメラを選択
316
- 3. 周囲の看板や店舗が見える位置で**「解析する」**ボタンを押
317
- 4. 複数回解析すると精度が上がります
 
318
 
319
  ### 注意事項
320
  - GPSは使用していません(映像のみで位置を推定)
321
  - コンビニ、飲食店、駅などが見えると精度が上がります
 
322
  """
323
  )
324
 
 
195
  def create_ui():
196
  """Gradio UIを作成"""
197
 
198
+ # ページ読み込み時に外カメラをデフォルトにするJavaScript
199
+ init_camera_js = """
200
+ () => {
201
+ // Gradioのカメラが起動したら外カメラに切り替える
202
+ const initRearCamera = async () => {
203
+ // 少し待ってからカメラを探す
204
+ await new Promise(r => setTimeout(r, 2000));
205
+
206
+ const video = document.querySelector('video');
207
+ if (!video) {
208
+ console.log('Video element not found, retrying...');
209
+ setTimeout(initRearCamera, 1000);
210
+ return;
211
+ }
212
+
213
+ // カメラが起動するまで待つ
214
+ if (!video.srcObject) {
215
+ console.log('Camera not started yet, retrying...');
216
+ setTimeout(initRearCamera, 1000);
217
+ return;
218
+ }
219
+
220
+ try {
221
+ const tracks = video.srcObject.getVideoTracks();
222
+ if (tracks.length > 0) {
223
+ tracks.forEach(track => track.stop());
224
+ }
225
+
226
+ // 外カメラを要求
227
+ const stream = await navigator.mediaDevices.getUserMedia({
228
+ video: { facingMode: { ideal: 'environment' } }
229
+ });
230
+ video.srcObject = stream;
231
+ console.log('外カメラに切り替え成功');
232
+ } catch (err) {
233
+ console.log('外カメラ切り替え失敗:', err);
234
+ }
235
+ };
236
+
237
+ // ページ読み込み後に実行
238
+ initRearCamera();
239
+ }
240
+ """
241
 
242
  with gr.Blocks(
243
  title="どこカメ - リアルタイム位置特定",
244
  theme=gr.themes.Soft(),
245
+ js=init_camera_js,
246
  ) as demo:
247
  gr.Markdown(
248
  """
 
257
  webcam = gr.Image(
258
  sources=["webcam"],
259
  streaming=False,
260
+ label="📷 カメラで撮影してから解析ボタンを押してください",
261
  mirror_webcam=False,
262
  )
263
 
264
  with gr.Row():
265
  # 解析ボタン
266
+ analyze_btn = gr.Button("🔍 解析する", variant="primary", size="lg")
267
  # カメラ切り替えボタン
268
  switch_camera_btn = gr.Button("🔄 内/外カメラ切替", variant="secondary")
269
 
 
353
  """
354
  ---
355
  ### 使い方
356
+ 1. カメラを許可して起動(自動で外カメラが選択されます)
357
+ 2. 必要に応じて**「内/外カメラ切替」**で切り替え
358
+ 3. 周囲の看板や店舗が見える位置で**カメラUI内の撮影ボタン**を押して写真を撮る
359
+ 4. **「解析する」**ボタンを押して位置を特定
360
+ 5. 複数回解析すると精度が上がります
361
 
362
  ### 注意事項
363
  - GPSは使用していません(映像のみで位置を推定)
364
  - コンビニ、飲食店、駅などが見えると精度が上がります
365
+ - **先に写真を撮ってから解析ボタンを押してください**
366
  """
367
  )
368