--- sidebar_position: 99 title: ローカルサーバーでマイク・カメラを使う方法 description: HTTP + IPアドレスでブラウザのマイク・カメラが動かない問題の解決策 hide_table_of_contents: false displayed_sidebar: null image: ./banner.png --- # ローカルサーバーでマイク・カメラを使う方法 ## 問題 ローカルネットワーク上のサーバー(例: `http://192.168.1.100:7860`)にブラウザからアクセスすると、マイクやカメラが使えない。 ``` NotAllowedError: Permission denied ``` ## 原因 ブラウザの **セキュアコンテキスト** 制限。`getUserMedia()`(マイク・カメラ API)は以下の条件でのみ動作: - `https://` — HTTPS接続 - `http://localhost` — ローカルホスト - `http://127.0.0.1` — ループバック **`http://192.168.x.x` は対象外。** ## 解決策 ### 方法1: SSHトンネル(推奨) 最も簡単。リモートサーバーのポートを `localhost` にフォワード。 ```bash ssh -L 7860:localhost:7860 user@192.168.1.100 ``` その後 `http://localhost:7860` でアクセス → マイク使用可能! **複数ポートの場合:** ```bash ssh -L 7860:localhost:7860 -L 8000:localhost:8000 user@192.168.1.100 ``` ### 方法2: Chromeフラグで許可 テスト用途に。特定のIPをセキュアコンテキストとして扱う。 1. Chromeで `chrome://flags` にアクセス 2. `Insecure origins treated as secure` を検索 3. 許可するURLを追加(例: `http://192.168.1.100:7860`) 4. Chrome再起動 :::warning セキュリティが低下するため、開発・テスト用途に限定してください。 ::: ### 方法3: 自己署名証明書でHTTPS化 チーム共有や本格運用向け。サーバー側でHTTPSを有効化。 #### Step 1: 証明書を生成 サーバー側で以下を実行: ```bash openssl req -x509 -newkey rsa:4096 \ -keyout key.pem \ -out cert.pem \ -days 365 \ -nodes \ -subj "/CN=192.168.1.100" \ -addext "subjectAltName=IP:192.168.1.100" ``` | オプション | 説明 | |-----------|------| | `-keyout key.pem` | 秘密鍵ファイル(サーバーが使う、外部に漏らさない) | | `-out cert.pem` | 証明書ファイル(クライアントに配布可能) | | `-days 365` | 有効期限(1年) | | `-nodes` | パスフレーズなし(サーバー自動起動用) | | `-subj "/CN=..."` | Common Name(IPアドレスまたはホスト名) | | `-addext "subjectAltName=..."` | SANs(最近のブラウザで必須) | **生成されるファイル:** ``` key.pem # 秘密鍵(絶対に公開しない) cert.pem # 証明書(クライアントに配布OK) ``` #### Step 2: サーバーで証明書を使う **Gradio:** ```bash python app.py --ssl-keyfile key.pem --ssl-certfile cert.pem ``` **FastAPI / Uvicorn:** ```bash uvicorn main:app --host 0.0.0.0 --port 8000 \ --ssl-keyfile key.pem --ssl-certfile cert.pem ``` **Python http.server(簡易):** ```python import ssl import http.server context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain('cert.pem', 'key.pem') server = http.server.HTTPServer(('0.0.0.0', 8000), http.server.SimpleHTTPRequestHandler) server.socket = context.wrap_socket(server.socket, server_side=True) server.serve_forever() ``` **Node.js / Express:** ```javascript const https = require('https'); const fs = require('fs'); const app = require('./app'); https.createServer({ key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') }, app).listen(8000); ``` #### Step 3: ブラウザでアクセス `https://192.168.1.100:8000` にアクセスすると警告が出る: **Chrome:** 1. 「この接続ではプライバシーが保護されません」と表示 2. 「詳細設定」をクリック 3. 「192.168.1.100 にアクセスする(安全ではありません)」をクリック **Firefox:** 1. 「警告: 潜在的なセキュリティリスクあり」と表示 2. 「詳細」→「危険性を承知で続行」 **Safari:** 1. 「この接続はプライベートではありません」と表示 2. 「詳細を表示」→「このWebサイトを閲覧」 #### Step 4: 証明書を信頼済みに登録(オプション) 毎回警告を出したくない場合、証明書をOSに登録。 **macOS:** ```bash sudo security add-trusted-cert -d -r trustRoot \ -k /Library/Keychains/System.keychain cert.pem ``` **Ubuntu/Debian:** ```bash sudo cp cert.pem /usr/local/share/ca-certificates/myserver.crt sudo update-ca-certificates ``` **Windows:** 1. `cert.pem` を `cert.crt` にリネーム 2. ダブルクリック → 「証明書のインストール」 3. 「ローカルマシン」→「信頼されたルート証明機関」に配置 :::tip チームで共有する場合は `cert.pem` を配布し、各メンバーがOSに登録すると便利です。 ::: ### 方法4: ngrok / Cloudflare Tunnel 外部サービス経由でHTTPS URL を取得。 ```bash ngrok http 7860 # → https://xxxx.ngrok.io が発行される ``` ## 早見表 | 方法 | 難易度 | セキュリティ | 用途 | |------|--------|------------|------| | SSHトンネル | ★☆☆ | ◎ | 開発・日常利用 | | Chromeフラグ | ★☆☆ | △ | 一時的なテスト | | 自己署名証明書 | ★★☆ | ○ | チーム共有 | | ngrok等 | ★★☆ | ◎ | 外部共有・デモ | ## 関連 - [DGX SparkでVibeVoice ASRを動かす](/tech/dgx-spark-vibevoice-asr/) — リアルタイム音声認識