--- title: MediaDevices.getUserMedia() slug: Web/API/MediaDevices/getUserMedia tags: - API - Audio - Capture - Media Capture and Streams API - Media Streams API - MediaDevices - Method - Photos - Reference - Video - WebRTC - getusermedia - メソッド translation_of: Web/API/MediaDevices/getUserMedia ---
{{domxref("MediaDevices")}}.getUserMedia()
メソッドは、要求された種類のメディアを含むトラックを持つ {{domxref("MediaStream")}} を生成するメディア入力を使用する許可をユーザーに求めます。このストリームには、例えば、動画トラック (カメラ、ビデオ録画機器、スクリーン共有サービスなどのような、ハードウェアまたは仮想ビデオソースによって生み出される)、音声トラック (同様に、マイク、A/D 変換器などの物理的または仮想オーディオソースによって生み出される)、その他の可能な種別を含めることができます。
これは {{domxref("MediaStream")}} オブジェクトに解決する {{jsxref("Promise")}} を返します。ユーザーが拒否した場合や、一致するメディアが利用できない場合、 Promise はそれぞれ NotAllowedError
または NotFoundError
で拒否されます。
メモ: ユーザーが選択する必要が全くなく、リクエストを単純に無視できる場合、返却された Promise が解決または拒絶のどちらにもならない可能性があります。
一般的に、 {{domxref("MediaDevices")}} のシングルトンオブジェクトは以下のように、 {{domxref("navigator.mediaDevices")}} を使用してアクセスします。
async function getMedia(constraints) { let stream = null; try { stream = await navigator.mediaDevices.getUserMedia(constraints); /* ストリームを使用 */ } catch(err) { /* エラーを処理 */ } }
同様に、生の Promise を直接使用すると、コードは次のようになります。
navigator.mediaDevices.getUserMedia(constraints) .then(function(stream) { /* ストリームを使用 */ }) .catch(function(err) { /* エラーを処理 */ });
メモ: 現在の文書が安全に読み込まれなかった場合は、 navigator.mediaDevices
は undefined
になり、 getUserMedia()
を使用することはできません。{{anch("Security", "セキュリティ")}}の節に、この件やその他の getUserMedia()
の使用に関するセキュリティ問題の詳細があります。
var promise = navigator.mediaDevices.getUserMedia(constraints);
constraints
{{domxref("MediaStreamConstraints")}} オブジェクトで、それぞれの種類のために何らかの要件に沿って要求するメディアの種類を指定します。
constraints
引数は MediaStreamConstraints
であり、二つのメンバー video
および audio
を持ち、要求されたメディアの種類を記述します。どちらか、または両方を指定する必要があります。ブラウザーが指定された条件に合う指定されたタイプを持つすべてのメディアトラックを発見できない場合、返却された Promise は NotFoundError
で拒否されます。
次の例は特定の要件なしに audio と video の両方を要求します。
{ audio: true, video: true }
メディアの種類に true
が指定された場合、結果のストリームはそのタイプのトラックが中にある必要があります。何らかの理由で含めることができない場合、 getUserMedia()
の呼び出しはエラーが返ります。
ユーザーのカメラやマイクについての情報は、プライバシー上の理由からアクセスできませんが、アプリケーションは追加の制約を使用することで、カメラやマイクの能力を必要に応じて要求することができます。次の例は、 1280x720 のカメラ解像度の設定を表しています。
{ audio: true, video: { width: 1280, height: 720 } }
ブラウザーはこれに忠実であろうとしますが、正確に一致するものが使用できない場合や、ユーザーがこれをオーバーライドした場合は、異なる解像度を返すことがあります。
機能を必要とするには、 min
, max
, exact
(つまり min == max
) の各キーワードが使用してください。次の例は 1280x720 の最小解像度を要求します。
{ audio: true, video: { width: { min: 1280 }, height: { min: 720 } } }
この解像度以上のカメラがない場合、返却された Promise は OverconstrainedError
として拒否され、ユーザーには通知されません。
動作に違いが発生する理由は、 min
, max
, exact
の各キーワードが本質的に必須であるためです。それに対して ideal
と呼ばれるプレーンな値とキーワードはそうではありません。より充実したサンプルを示します。
{ audio: true, video: { width: { min: 1024, ideal: 1280, max: 1920 }, height: { min: 776, ideal: 720, max: 1080 } } }
ideal
の値は、使用された場合は重みをもち、つまりブラウザーは ideal の値からみた最適距離が最小になるような設定 (および、複数ある場合はカメラ) を見つけようとすることを意味します。
プレインの値は本質的に ideal ですので、これは上記の解像度の例を以下のように書くこともできることを意味します。
{ audio: true, video: { width: { ideal: 1280 }, height: { ideal: 720 } } }
すべての constraint が数字とは限りません。例えば、次の例はリアカメラよりもフロントカメラを (利用できるなら) を選好します。
{ audio: true, video: { facingMode: "user" } }
リアカメラが必要であれば、次のようにします。
{ audio: true, video: { facingMode: { exact: "environment" } } }
他の数値以外の制約として、 deviceId
の制約があります。 deviceId
が {{domxref("mediaDevices.enumerateDevices()")}} から分かっているのであれば、これを使用して特定の機器を要求することができます。
{ video: { deviceId: myPreferredCameraDeviceId } }
上記のものは要求されたカメラを返しますが、特定したカメラが利用できない場合は別なカメラを返します。また、特定のカメラが必要なのであれば、以下のようにすることができます。
{ video: { deviceId: { exact: myExactCameraOrBustDeviceId } } }
要求されたメディアが正しく取得できたときに {{domxref("MediaStream")}} を受け取るハンドラーを示す {{jsxref("Promise")}} を返します。
返却されたpromiseの拒否は {{ domxref("DOMException") }}に構成された{{ domxref("MediaStreamError") }}として生成されます。関連するエラーは以下の通りです。
AbortError
NotReadableError
が生じるような問題も起きなかったが、デバイスを利用できない何らかの問題が発生した。NotAllowedError
SecurityError
for this instead; SecurityError
has taken on a new meaning.NotFoundError
NotReadableError
OverconstrainedError
OverconstrainedError
, and has a constraint
property whose string value is the name of a constraint which was impossible to meet, and a message
property containing a human-readable string explaining the problem.
SecurityError
getUserMedia()
was called. The mechanism by which user media support is enabled and disabled is left up to the individual user agent.TypeError
false
. This can also happen if you try to call getUserMedia()
in an insecure context, since {{domxref("navigator.mediaDevices")}} is undefined
in an insecure context.As an API that may involve significant privacy concerns, getUserMedia()
's specification lays out a wide array of privacy and security requirements that browsers are obligated to meet.
getUserMedia()
is a powerful feature which can only be used in secure contexts; in insecure contexts, navigator.mediaDevices
is undefined
, preventing access to getUserMedia()
. A secure context is, in short, a page loaded using HTTPS or the file:///
URL scheme, or a page loaded from localhost
.
In addition, user permission is always required to access the user's audio and video inputs. Only a window's top-level document context for a valid origin can even request permission to use getUserMedia()
, unless the top-level context expressly grants permission for a given {{HTMLElement("iframe")}} to do so using Feature Policy. Otherwise, the user will never even be asked for permission to use the input devices.
For additional details on these requirements and rules, how they are reflected in the context in which your code is running, and about how browsers manage user privacy and security issues, read on.
As an API that may involve significant privacy concerns, getUserMedia()
is held by the specification to very specific requirements for user notification and permission management. First, getUserMedia()
must always get user permission before opening any media gathering input such as a webcam or microphone. Browsers may offer a once-per-domain permission feature, but they must ask at least the first time, and the user must specifically grant ongoing permission if they choose to do so.
Of equal importance are the rules around notification. Browsers are required to display an indicator that shows that a camera or microphone is in use, above and beyond any hardware indicator that may exist. They must also show an indicator that permission has been granted to use a device for input, even if the device is not actively recording at the moment.
For example in Firefox, the URL bar displays a pulsing red icon to indicate that recording is underway. The icon is gray if the permission is in place but recording is not currently underway. The device's physical light is used to indicate whether or not recording is currently active. If you've muted your camera (so-called "facemuting"), your camera's activity light goes out to indicate that the camera is not actively recording you, without discarding the permission to resume using the camera once muting is over.
There are a number of ways security management and controls in a {{Glossary("user agent")}} can cause getUserMedia()
to return a security-related error.
Note: The security model for getUserMedia()
is still somewhat in flux. The originally-designed security mechanism is in the process of being replaced with Feature Policy, so various browsers have different levels of security support, using different mechanisms. You should test your code carefully on a variety of devices and browsers to be sure it is as broadly compatible as possible
The Feature Policy security management feature of {{Glossary("HTTP")}} is in the process of being introduced into browsers, with support available to some extent in many browsers (though not always enabled by default, as in Firefox). getUserMedia()
is one method which will require the use of Feature Policy, and your code needs to be prepared to deal with this. For example, you may need to use the {{htmlattrxref("allow", "iframe")}} attribute on any {{HTMLElement("iframe")}} that uses getUserMedia()
, and pages that use getUserMedia()
will eventually need to supply the {{HTTPHeader("Feature-Policy")}} header.
The two permissions that apply to getUserMedia()
are camera
and microphone
.
For example, this line in the HTTP headers will enable use of a camera for the document and any embedded {{HTMLElement("iframe")}} elements that are loaded from the same origin:
Feature-Policy: camera 'self'
This will request access to the microphone for the current origin and the specific origin https://developer.mozilla.org:
Feature-Policy: microphone 'self' https://developer.mozilla.org
If you're using getUserMedia()
within an <iframe>
, you can request permission just for that frame, which is clearly more secure than requesting a more general permission. Here, indicate we need the ability to use both camera and microphone:
<iframe src="https://mycode.example.net/etc" allow="camera;microphone"> </iframe>
Read our guide, Using Feature Policy, to learn more about how it works.
The getUserMedia()
method is only available in secure contexts. A secure context is one the browser is reasonably confident contains a document which was loaded securely, using HTTPS/TLS, and has limited exposure to insecure contexts. If a document isn't loaded in a secure context, the {{domxref("navigator.mediaDevices")}} property is undefined
, making access to getUserMedia()
impossible.
Attempting to access getUserMedia()
in this situation will result in a TypeError
.
Because of the obvious security concern associated with getUserMedia()
if used unexpectedly or without security being carefully managed, it can only be used in secure contexts. There are a number of insecure ways to load a document that might, in turn, attempt to call getUserMedia()
. The following are examples of situations in which getUserMedia()
is not permitted to be called:
getUserMedia()
unless the <iframe>
has its {{htmlattrxref("sandbox", "iframe")}} attribute set to allow-same-origin
.data://
or blob://
URL which has no origin (such as when one of these URLs is typed by the user into the address bar) cannot call getUserMedia()
. These kinds of URLs loaded from JavaScript code inherit the script's permissions.この例ではカメラの解像度の設定を与えて、結果の {{domxref("MediaStream")}} オブジェクトを vide 要素に割り当てます。
// Prefer camera resolution nearest to 1280x720. var constraints = { audio: true, video: { width: 1280, height: 720 } }; navigator.mediaDevices.getUserMedia(constraints) .then(function(mediaStream) { var video = document.querySelector('video'); video.srcObject = mediaStream; video.onloadedmetadata = function(e) { video.play(); }; }) .catch(function(err) { console.log(err.name + ": " + err.message); }); // always check for errors at the end.
Here's an example of using navigator.mediaDevices.getUserMedia()
, with a polyfill to cope with older browsers. Note that this polyfill does not correct for legacy differences in constraints syntax, which means constraints won't work well across browsers. It is recommended to use the adapter.js polyfill instead, which does handle constraints.
// Older browsers might not implement mediaDevices at all, so we set an empty object first if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {}; } // Some browsers partially implement mediaDevices. We can't just assign an object // with getUserMedia as it would overwrite existing properties. // Here, we will just add the getUserMedia property if it's missing. if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function(constraints) { // First get ahold of the legacy getUserMedia, if present var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // Some browsers just don't implement it - return a rejected promise with an error // to keep a consistent interface if (!getUserMedia) { return Promise.reject(new Error('getUserMedia is not implemented in this browser')); } // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise return new Promise(function(resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); } } navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then(function(stream) { var video = document.querySelector('video'); // Older browsers may not have srcObject if ("srcObject" in video) { video.srcObject = stream; } else { // Avoid using this in new browsers, as it is going away. video.src = window.URL.createObjectURL(stream); } video.onloadedmetadata = function(e) { video.play(); }; }) .catch(function(err) { console.log(err.name + ": " + err.message); });
帯域幅に制限のあるWebRTC通信のようなケースでは、低フレームレートが望ましいかもしれません。
var constraints = { video: { frameRate: { ideal: 10, max: 15 } } };
携帯電話での例。
var front = false; document.getElementById('flip-button').onclick = function() { front = !front; }; var constraints = { video: { facingMode: (front? "user" : "environment") } };
仕様書 | 状態 | 備考 |
---|---|---|
{{SpecName('Media Capture', '#dom-mediadevices-getusermedia', 'MediaDevices.getUserMedia()')}} | {{Spec2('Media Capture')}} | 初回定義 |
{{Compat("api.MediaDevices.getUserMedia")}}
getUserMedia()
を使用して動画ではなくスチル写真を撮る方法