// 既存の startQuagga / stopQuagga / startBtn 等はそのまま使う想定 async function takePhotoAndDecode() { resultEl.textContent = "静止画撮影中…"; let createdTempStream = false; let tempTrack = null; let needRestartQuagga = false; try { // 1) Quagga が動いているなら一時停止してカメラを解放 if (active) { needRestartQuagga = true; stopQuagga(); // 少し待つ(カメラ解放の猶予) await new Promise(r => setTimeout(r, 300)); } // 2) 高解像度ストリームを取得(ImageCapture 用) try { const s = await navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment", width: { ideal: 4032 }, height: { ideal: 3024 } } }); tempTrack = s.getVideoTracks()[0]; createdTempStream = true; } catch (err) { throw new Error("高解像度ストリームの取得に失敗しました: " + (err && err.message ? err.message : err)); } // 3) ImageCapture の存在確認 if (typeof ImageCapture === "undefined") { throw new Error("ImageCapture API が利用できません(ブラウザ非対応)。代替でファイル入力を使ってください。"); } // 4) 撮影 const imageCapture = new ImageCapture(tempTrack); const blob = await imageCapture.takePhoto(); // ここで例外が出る場合あり if (!blob) throw new Error("撮影に失敗しました(blob が空)"); // 5) blob -> ImageBitmap -> canvas -> dataURL const imgBitmap = await createImageBitmap(blob); const canvas = document.createElement('canvas'); canvas.width = imgBitmap.width; canvas.height = imgBitmap.height; const ctx = canvas.getContext('2d'); ctx.drawImage(imgBitmap, 0, 0); // 必要ならここで前処理(グレースケール・コントラスト)を入れる const dataUrl = canvas.toDataURL('image/jpeg', 0.9); resultEl.textContent = "デコード中…"; // 6) Quagga.decodeSingle に渡す(非同期コールバック) await new Promise((resolve) => { Quagga.decodeSingle({ src: dataUrl, numOfWorkers: 0, inputStream: { size: 800 }, decoder: { readers: ["ean_reader","ean_8_reader","upc_reader","code_128_reader","code_39_reader"] } }, function(result) { if (result && result.codeResult) { const code = result.codeResult.code; resultEl.textContent = `静止画で検出: ${code}`; // 遷移や処理 setTimeout(() => window.location.href = `https://jp.mercari.com/search?keyword=${encodeURIComponent(code)}`, 300); } else { resultEl.textContent = "静止画でも検出できませんでした。もう一度撮影してください。"; } resolve(); }); // セーフティタイムアウト(万が一コールバックが来ない場合) setTimeout(() => { resultEl.textContent = "デコードがタイムアウトしました。もう一度試してください。"; resolve(); }, 8000); }); } catch (err) { console.error("静止画デコードエラー:", err); resultEl.textContent = "静止画デコードに失敗: " + (err && err.message ? err.message : err); } finally { // 7) 一時トラックを停止して解放 try { if (createdTempStream && tempTrack) tempTrack.stop(); } catch(e){} // 8) 必要なら Quagga を再開 if (needRestartQuagga) { // 少し待ってから再開(カメラ解放の余裕) setTimeout(() => startQuagga(), 400); } } }