diff options
| author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
|---|---|---|
| committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
| commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
| tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/ja/web/api/media_streams_api | |
| parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
| download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip | |
initial commit
Diffstat (limited to 'files/ja/web/api/media_streams_api')
| -rw-r--r-- | files/ja/web/api/media_streams_api/constraints/index.html | 567 | ||||
| -rw-r--r-- | files/ja/web/api/media_streams_api/index.html | 131 |
2 files changed, 698 insertions, 0 deletions
diff --git a/files/ja/web/api/media_streams_api/constraints/index.html b/files/ja/web/api/media_streams_api/constraints/index.html new file mode 100644 index 0000000000..3be8a4ed55 --- /dev/null +++ b/files/ja/web/api/media_streams_api/constraints/index.html @@ -0,0 +1,567 @@ +--- +title: 能力、制約、そして設定 +slug: Web/API/Media_Streams_API/Constraints +tags: + - Advanced + - Audio + - Constraints + - Example + - Guide + - Media + - Media Capture and Streams API + - Media Streams API + - Settings + - Video + - WebRTC + - capabilities +translation_of: Web/API/Media_Streams_API/Constraints +--- +<div>{{DefaultAPISidebar("Media Capture and Streams")}}</div> + +<p>歴史的に、Web API と密接に連携するウェブ用のスクリプトを作成することには、よく知られた課題がありました。 多くの場合、コードは、API が存在するかどうか、存在する場合は、それを実行している{{Glossary("user agent","ユーザーエージェント")}}の制限を知る必要があります。 これを理解するのは難しい場合が多く、通常、実行している{{Glossary("user agent","ユーザーエージェント")}}(またはブラウザー)とそのバージョンの組み合わせを調べ、特定のオブジェクトが存在するかどうかを確認したり、さまざまなものが機能するかどうかを確認したり、どのエラーが発生したかを判断したりする必要がありました。 その結果、非常に脆弱なコードが大量に発生するか、このような問題を解決するライブラリに依存したり、{{Glossary("polyfill", "ポリフィル")}}を実装して実装の穴にパッチを当てたりしました。</p> + +<p><span class="seoSummary"><strong>制約</strong>(constraints)と<strong>能力</strong>(capabilities)の双子の概念により、ブラウザーとウェブサイトまたはアプリは、ブラウザーの実装がサポートする<strong>制約可能なプロパティ</strong>(constrainable properties)と、それぞれに対してサポートする値に関する情報を交換できます。 この記事では、能力と制約およびメディアの設定について説明し、{{anch("Example Constraint exerciser", "制約エクササイザー")}}(Constraint Exerciser)と呼ばれる例を含みます。</span> 制約エクササイザーを使用すると、コンピューターの A/V 入力デバイス(ウェブカメラやマイクなど)からの音声トラックと動画トラックに適用されるさまざまな制約セットの結果を試すことができます。</p> + +<h2 id="Overview" name="Overview">概要</h2> + +<p>プロセスは次のように動作します(例として {{domxref("MediaStreamTrack")}} を使用)。</p> + +<ol> + <li>必要に応じて、{{domxref("MediaDevices.getSupportedConstraints()")}} を呼び出して、<strong>サポートしている制約</strong>(supported constraints)のリストを取得します。 これにより、ブラウザーが知っている制約可能なプロパティがわかります。 これは必ずしも必要なわけではありません。 知らないものは指定すると単に無視されるためです。 ただし、それなしでは手に入らないものがある場合は、リストに載っていることを確認することから始めることができます。</li> + <li>使用したいプロパティをサポートしているかどうかをスクリプトが認識すると、トラックの <code>getCapabilities()</code> メソッドによって返されたオブジェクトを調べることにより、API とその実装の<strong>能力</strong>を確認できます。 このオブジェクトは、サポートしている各制約と、サポートしている値または値の範囲をリストします。</li> + <li>最後に、トラックの <code>applyConstraints()</code> メソッドを呼び出して、好みの制約可能なプロパティに使用する値または値の範囲を指定することにより、必要に応じて API を構成します。</li> + <li>トラックの <code>getConstraints()</code> メソッドは、<code>applyConstraints()</code> の最新の呼び出しに渡された制約セットを返します。 これは、要求された値を調整する必要があるプロパティと、プラットフォームのデフォルト値が表されていないため、トラックの実際の現在の状態を表していない場合があります。 トラックの現在の構成を完全に表現するには、<code>getSettings()</code> を使用します。</li> +</ol> + +<p>Media Stream API では、{{domxref("MediaStream")}} と {{domxref("MediaStreamTrack")}} の両方に制約可能なプロパティがあります。</p> + +<h2 id="Determining_if_a_constraint_is_supported" name="Determining_if_a_constraint_is_supported">制約をサポートしているかどうかの判断</h2> + +<p>特定の制約をユーザーエージェントがサポートしているかどうかを知る必要がある場合は、次のように {{domxref("MediaDevices.getSupportedConstraints", "navigator.mediaDevices.getSupportedConstraints()")}} を呼び出して、ブラウザーが知っている制約可能なプロパティのリストを取得します。</p> + +<pre class="brush: js">let supported = navigator.mediaDevices.getSupportedConstraints(); + +document.getElementById("frameRateSlider").disabled = !supported["frameRate"];</pre> + +<p>この例では、サポートしている制約を取得し、<code>frameRate</code> 制約をサポートしていない場合、ユーザーがフレームレートを構成できるコントロールを無効にします。</p> + +<h2 id="How_constraints_are_defined" name="How_constraints_are_defined">制約の定義方法</h2> + +<p>単一の制約は、目的の値または値の範囲が指定されている制約可能なプロパティと名前が一致するオブジェクトです。 このオブジェクトには、0 個以上の個別の制約と、<code>advanced</code> というオプションのサブオブジェクトが含まれます。 このサブオブジェクトには、ユーザーエージェントが可能な限り満たす必要がある 0 個以上の制約の別のセットが含まれます。 ユーザーエージェントは、制約セットで指定された順序で制約を満たすことを試みます。</p> + +<p>理解すべき最も重要なことは、ほとんどの制約は必要条件ではないということです。 それよりむしろ、それらは要求です。 例外があり、すぐにそれらに到達します。</p> + +<h3 id="Requesting_a_specific_value_for_a_setting" name="Requesting_a_specific_value_for_a_setting">設定に特定の値を要求</h3> + +<p>最も簡単には、各制約は、設定に必要な値を示す特定の値である場合があります。 例えば、次のようにです。</p> + +<pre class="brush: js">let constraints = { + width: 1920, + height: 1080, + aspectRatio: 1.777777778 +}; + +myTrack.applyConstraints(constraints);</pre> + +<p>この場合、制約は、ほぼすべてのプロパティで任意の値が適切であることを示しますが、標準の 16:9 アスペクト比で標準の高解像度(HD)動画サイズが望ましいことを示します。 結果のトラックがこれらのいずれかに一致するという保証はありませんが、ユーザーエージェントは可能な限り一致するように最善を尽くす必要があります。</p> + +<p>プロパティの優先順位付けは簡単です。 2つのプロパティの要求値が相互に排他的である場合、制約セットの最初にリストされている値を使用します。 例として、上記のコードを実行しているブラウザーは 1920x1080 のトラックを提供できないが、1920x900 を提供できる場合、それを提供します。</p> + +<p>単一の値を指定するこれらのような単純な制約は、常に必須でないものとして扱われます。 ユーザーエージェントは、あなたが要求したものを提供しようとしますが、あなたが得るものが一致することを保証しません。 しかしながら、{{domxref("MediaStreamTrack.applyConstraints()")}} を呼び出すときにプロパティに単純な値を使用すると、これらの値は必要条件ではなく要求と見なされるため、要求は常に成功します。</p> + +<h3 id="Specifying_a_range_of_values" name="Specifying_a_range_of_values">値の範囲の指定</h3> + +<p>場合によっては、範囲内の任意の値がプロパティの値として受け入れられることがあります。 範囲は、最小値(<code>min</code>)と最大値(<code>max</code>)のいずれかまたは両方を指定でき、必要に応じて範囲内で理想的な値(<code>ideal</code>)を最終結果として指定できます。 理想的な値を指定すると、ブラウザーは、指定された他の制約に応じて、その値にできるだけ一致するように近づけようとします。</p> + +<pre class="brush: js">let supports = navigator.mediaDevices.getSupportedConstraints(); + +if (!supports["width"] || !supports["height"] || !supports["frameRate"] || !supports["facingMode"]) { + // 必要なプロパティが不足しているため、そのエラーを処理します。 +} else { + let constraints = { + width: { min: 640, ideal: 1920, max: 1920 }, + height: { min: 400, ideal: 1080 }, + aspectRatio: 1.777777778, + frameRate: { max: 30 }, + facingMode: { exact: "user" } + }; + + myTrack.applyConstraints(constraints).then(function() => { + /* 制約が正常に適用されたら何かをする */ + }).catch(function(reason) { + /* 制約を適用できませんでした。 reason が理由 */ + }); +} +</pre> + +<p>ここでは、一致を見つける必要のある制約可能なプロパティ(<code>width</code>、<code>height</code>、<code>frameRate</code>、<code>facingMode</code>)がサポートされていることを確認した後、幅は 640 以上 1920 以下(できれば 1920)、高さは 400 以上(理想的には 1080)、アスペクト比は 16:9(1.777777778)、フレームレートは 30 フレーム/秒以下を要求する制約を設定します。 さらに、唯一の許容可能な入力デバイスは、ユーザーに面したカメラ(自撮りカメラ)です。 <code>width</code>、<code>height</code>、<code>frameRate</code>、または <code>facingMode</code> の制約が満たされない場合、<code>applyConstraints()</code> によって返された promise は拒否されます。</p> + +<div class="note"> +<p><code>max</code>、<code>min</code>、<code>exact</code> のいずれかまたはすべてを使用して指定された制約は、常に必須として扱われます。 <code>applyConstraints()</code> を呼び出して、使用する制約を1つ以上を満たすことができない場合、promise は拒否されます。</p> +</div> + +<h3 id="Advanced_constraints" name="Advanced_constraints">高度な制約</h3> + +<p><code>advanced</code> プロパティを制約セットに追加すると、いわゆる高度な制約が作成されます。 このプロパティの値は、オプションと見なされる追加の制約セットの配列です。 この機能のユースケースはほとんどなく、仕様から取り除くことに関心があるため、ここでは説明しません。 詳細については、<a href="https://www.w3.org/TR/mediacapture-streams/#idl-def-Constraints">Media Capture and Streams 仕様のセクション 11、過去の例 2</a> を参照してください。</p> + +<h2 id="Checking_capabilities" name="Checking_capabilities">能力の確認</h2> + +<p>{{domxref("MediaStreamTrack.getCapabilities()")}} を呼び出して、サポートしているすべての能力と、そのそれぞれが現在のプラットフォームとユーザーエージェントで受け入れられる値または値の範囲のリストを取得できます。 この関数は、ブラウザーがサポートしている各制約可能なプロパティと、それらのプロパティのそれぞれがサポートしている値または値の範囲をリストする {{domxref("MediaTrackCapabilities")}} オブジェクトを返します。</p> + +<div class="note"> +<p><strong>注</strong>: <code>getCapabilities()</code> は、まだすべての主要なブラウザーで実装されていません。 とりあえず、あなたは必要なものを手に入れようとする必要があり、もしそれができなければ、その時点で何をすべきかを決定します。 例えば、{{bug(1179084)}} を参照してください。</p> +</div> + +<h2 id="Applying_constraints" name="Applying_constraints">制約の適用</h2> + +<p>制約を使用する最初の最も一般的な方法は、次のように {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}} を呼び出すときに制約を指定することです。</p> + +<pre class="brush: js">navigator.mediaDevices.getUserMedia({ + video: { + width: { min: 640, ideal: 1920 }, + height: { min: 400, ideal: 1080 }, + aspectRatio: { ideal: 1.7777777778 } + }, + audio: { + sampleSize: 16, + channelCount: 2 + } +}).then(stream => { + videoElement.srcObject = stream; +}).catch(handleError); +</pre> + +<p>この例では、<code>getUserMedia()</code> の時点で制約が適用され、動画のためのフォールバックを備えた理想的なオプションのセットが要求されます。</p> + +<div class="note"> +<p>1つ以上のメディア入力デバイス ID を指定して、入力ソースが許可される制限を設定できます。 利用可能なデバイスのリストを収集するには、{{domxref("MediaDevices.enumerateDevices", "navigator.mediaDevices.enumerateDevices()")}} を呼び出してから、目的の条件を満たす各デバイスに対して、その <code>deviceId</code> を <code>MediaConstraints</code> オブジェクトに追加して、最終的に <code>getUserMedia()</code> に渡します。</p> +</div> + +<p>次のようにトラックの {{domxref("MediaStreamTrack.applyConstraints", "applyConstraints()")}} メソッドを呼び出し、トラックに適用する制約を表すオブジェクトを渡すことで、既存の {{domxref("MediaStreamTrack")}} の制約を臨機応変に変更することもできます。</p> + +<pre class="brush: js">videoTrack.applyConstraints({ + width: 1920, + height: 1080 +}); +</pre> + +<p>このスニペットでは、<code>videoTrack</code> が参照する動画トラックが更新され、その解像度が可能な限り 1920x1080 ピクセル(1080p 高解像度)に一致するようになります。</p> + +<h2 id="Retrieving_current_constraints_and_settings" name="Retrieving_current_constraints_and_settings">現在の制約と設定の取得</h2> + +<p><strong>制約</strong>と<strong>設定</strong>(settings)の違いを覚えておくことは重要です。 制約は、({{domxref("MediaTrackConstraints")}} のドキュメントで説明されているように)さまざまな制約可能なプロパティに必要な値、希望する値、および受け入れる値を指定する方法です。 一方、設定は現在の各制約可能なプロパティの実際の値です。</p> + +<h3 id="Getting_the_constraints_in_effect" name="Getting_the_constraints_in_effect">実施されている制約の取得</h3> + +<p>現在メディアに適用されている制約セットを取得する必要がある場合は、次の例に示すように、{{domxref("MediaStreamTrack.getConstraints()")}} を呼び出すことでその情報を取得できます。</p> + +<pre class="brush: js">function switchCameras(track, camera) { + let constraints = track.getConstraints(); + constraints.facingMode = camera; + track.applyConstraints(constraints); +}</pre> + +<p>この関数は、{{domxref("MediaStreamTrack")}} と使用するカメラに面するモードを示す文字列を受け入れ、現在の制約を取得し、{{domxref("MediaTrackConstraints.facingMode")}} の値を指定された値に設定し、更新された制約セットを適用します。</p> + +<h3 id="Getting_the_current_settings_for_a_track" name="Getting_the_current_settings_for_a_track">トラックの現在の設定の取得</h3> + +<p>厳密な制約(<code>exact</code>)のみを使用しない限り(これは非常に制限的ですので、それの意味することを確認してください!)、制約が適用された後に実際に何が得られるかを保証するものではありません。 結果のメディアに実際に存在する制約可能なプロパティの値は、設定と呼ばれます。 メディアの実際の形式やその他のプロパティを知る必要がある場合は、{{domxref("MediaStreamTrack.getSettings()")}} を呼び出してこれらの設定を取得できます。 これは、ディクショナリ {{domxref("MediaTrackSettings")}} に基づくオブジェクトを返します。 例えば次のようにです。</p> + +<pre class="brush: js">function whichCamera(track) { + return track.getSettings().facingMode; +}</pre> + +<p>この関数は、<code>getSettings()</code> を使用して、トラックの制約可能なプロパティの現在使用中の値を取得し、{{domxref("MediaTrackSettings.facingMode", "facingMode")}} の値を返します。</p> + +<h2 id="Example_Constraint_exerciser" name="Example_Constraint_exerciser">例: 制約エクササイザー</h2> + +<p>この例では、音声トラックと動画トラックの制約セットを記述するソースコードを編集して、メディアの制約を試すことができるエクササイザーを作成します。 その後、これらの変更を適用して、ストリームの外観や、新しい制約を適用した後の実際のメディア設定の両方を含む結果を確認できます。</p> + +<p>この例の HTML と CSS は非常に単純であり、ここには示されていません。 {{LiveSampleLink("Example_Constraint_exerciser", "ここをクリックする")}}と、完全な例を見ることができます。</p> + +<div class="hidden"> +<h3 id="HTML_content" name="HTML_content">HTML content</h3> + +<pre class="brush: html"><p>メディアの制約を試してください! 左側の編集ボックスで動画トラックと音声トラックの制約セットを編集し、[制約の適用] ボタンをクリックして試してください。 ブラウザーが選択して使用している実際の設定は、右側のボックスに表示されます。 そのすべての下に、動画自体が表示されます。 +</p> +<p>[動画の開始] ボタンをクリックして開始します。</p> + +<h3>使用できる制約可能なプロパティ:</h3> +<ul id="supportedConstraints"> +</ul> +<div id="startButton" class="button"> + 動画の開始 +</div> +<div class="wrapper"> + <div class="leftside"> + <h3>要求した動画の制約:</h3> + <textarea id="videoConstraintEditor" cols=32 rows=8></textarea> + </div> + <div class="rightside"> + <h3>実際の動画の設定:</h3> + <textarea id="videoSettingsText" cols=32 rows=8 disabled></textarea> + </div> + <div class="leftside"> + <h3>要求した音声の制約:</h3> + <textarea id="audioConstraintEditor" cols=32 rows=8></textarea> + </div> + <div class="rightside"> + <h3>実際の音声の設定:</h3> + <textarea id="audioSettingsText" cols=32 rows=8 disabled></textarea> + </div> +</div> + +<div class="button" id="applyButton"> + 制約の適用 +</div> +<video id="video" autoplay></video> + +<div class="button" id="stopButton"> + 動画の停止 +</div> + +<div id="log"> +</div></pre> + +<h3 id="CSS_content" name="CSS_content">CSS content</h3> + +<pre class="brush: css">body { + font: 14px "Open Sans", "Arial", sans-serif; +} + +video { + margin-top: 20px; + border: 1px solid black; +} + +.button { + cursor: pointer; + width: 150px; + border: 1px solid black; + font-size: 16px; + text-align: center; + padding-top: 3px; + padding-bottom: 2px; + color: white; + background-color: darkgreen; +} + +.wrapper { + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 10px; + gap: 10px; + max-width: min-content; + margin-bottom: 10px; +} + +textarea { + width : 270px; + padding: 8px; +} + +h3 { + margin-bottom: 3px; +} + +#supportedConstraints { + column-count: 2; + -moz-column-count: 2; +} + +#log { + padding-top: 10px; +}</pre> + +<h3 id="JavaScript_content" name="JavaScript_content">JavaScript content</h3> + +<p>Now let's take a look at the JavaScript code that makes everything work.</p> +</div> + +<h4 id="Defaults_and_variables" name="Defaults_and_variables">デフォルトと変数</h4> + +<p>最初に、文字列としてデフォルトの制約セットがあります。 これらの文字列は編集可能な {{HTMLElement("textarea")}} に表示されますが、これはストリームの初期構成です。</p> + +<pre class="brush: js">let videoDefaultConstraintString = '{\n "width": 320,\n "height": 240,\n "frameRate": 30\n}'; +let audioDefaultConstraintString = '{\n "sampleSize": 16,\n "channelCount": 2,\n "echoCancellation": false\n}'; +</pre> + +<p>これらのデフォルトは、かなり一般的なカメラ構成を要求しますが、特に重要なプロパティであることを主張しません。 ブラウザーは、これらの設定に一致するように最善を尽くす必要がありますが、近い一致と見なされるものなら何でもそれで解決します。</p> + +<p>次に、動画トラックおよび音声トラックの {{domxref("MediaTrackConstraints")}} オブジェクトを保持する変数と、動画トラックおよび音声トラック自体への参照を保持する変数を <code>null</code> に初期化します。</p> + +<pre class="brush: js">let videoConstraints = null; +let audioConstraints = null; + +let audioTrack = null; +let videoTrack = null; +</pre> + +<p>そして、アクセスする必要のあるすべての要素への参照を取得します。</p> + +<pre class="brush: js">let videoElement = document.getElementById("video"); +let logElement = document.getElementById("log"); +let supportedConstraintList = document.getElementById("supportedConstraints"); +let videoConstraintEditor = document.getElementById("videoConstraintEditor"); +let audioConstraintEditor = document.getElementById("audioConstraintEditor"); +let videoSettingsText = document.getElementById("videoSettingsText"); +let audioSettingsText = document.getElementById("audioSettingsText"); +</pre> + +<p>これらの要素は次のとおりです。</p> + +<dl> + <dt><code>videoElement</code></dt> + <dd>ストリームを表示する {{HTMLElement("video")}} 要素。</dd> + <dt><code>logElement</code></dt> + <dd>エラーメッセージやその他のログの種類の出力が書き込まれる {{HTMLElement("div")}}。</dd> + <dt><code>supportedConstraintList</code></dt> + <dd>ユーザーのブラウザーがサポートしている各制約可能なプロパティの名前をプログラムで追加する {{HTMLElement("ul")}}(順序なしリスト)。</dd> + <dt><code>videoConstraintEditor</code></dt> + <dd>ユーザーが動画トラックの制約セットのコードを編集できるようにする {{HTMLElement("textarea")}} 要素。</dd> + <dt><code>audioConstraintEditor</code></dt> + <dd>ユーザーが音声トラックの制約セットのコードを編集できるようにする {{HTMLElement("textarea")}} 要素。</dd> + <dt><code>videoSettingsText</code></dt> + <dd> 動画トラックの制約可能なプロパティの現在の設定を表示する {{HTMLElement("textarea")}}(常に <code>disabled</code>)。</dd> + <dt><code>audioSettingsText</code></dt> + <dd>音声トラックの制約可能なプロパティの現在の設定を表示する {{HTMLElement("textarea")}}(常に <code>disabled</code>)。</dd> +</dl> + +<p>最後に、2つの制約セットエディター要素の現在の内容をデフォルトに設定します。</p> + +<pre class="brush: js">videoConstraintEditor.value = videoDefaultConstraintString; +audioConstraintEditor.value = audioDefaultConstraintString;</pre> + +<h4 id="Updating_the_settings_display" name="Updating_the_settings_display">設定の表示の更新</h4> + +<p>各制約セットエディターの右側には、トラックの構成可能なプロパティの現在の構成を表示するために使用する2番目のテキストボックスがあります。 この表示を関数 <code>getCurrentSettings()</code> で更新します。 この関数は、音声トラックと動画トラックの現在の設定を取得し、{{htmlattrxref("value", "textarea")}} を設定することで対応するコードをトラックの設定表示ボックスに挿入します。</p> + +<pre class="brush: js">function getCurrentSettings() { + if (videoTrack) { + videoSettingsText.value = JSON.stringify(videoTrack.getSettings(), null, 2); + } + if (audioTrack) { + audioSettingsText.value = JSON.stringify(audioTrack.getSettings(), null, 2); + } +} +</pre> + +<p>これは、以下に示すように、更新した制約を適用するときだけでなく、ストリームの最初の起動後にも呼び出されます。</p> + +<h4 id="Building_the_track_constraint_set_objects" name="Building_the_track_constraint_set_objects">トラックの制約セットオブジェクトの構築</h4> + +<p><code>buildConstraints()</code> 関数は、2つのトラックの制約セット編集ボックス内のコードを使用して、音声トラックと動画トラックの {{domxref("MediaTrackConstraints")}} オブジェクトを構築します。</p> + +<pre class="brush: js">function buildConstraints() { + try { + videoConstraints = JSON.parse(videoConstraintEditor.value); + audioConstraints = JSON.parse(audioConstraintEditor.value); + } catch(error) { + handleError(error); + } +} +</pre> + +<p>これは {{jsxref("JSON.parse()")}} を使用して、各エディター内のコードをオブジェクトに解析します。 <code>JSON.parse()</code> の呼び出しのどちらかが例外をスローした場合、<code>handleError()</code> が呼び出されてエラーメッセージがログに出力されます。</p> + +<h4 id="Configuring_and_starting_the_stream" name="Configuring_and_starting_the_stream">ストリームの構成と開始</h4> + +<p><code>startVideo()</code> メソッドは、動画ストリームのセットアップと開始を処理します。</p> + +<ol> +</ol> + +<pre class="brush: js">function startVideo() { + buildConstraints(); + navigator.mediaDevices.getUserMedia({ + video: videoConstraints, + audio: audioConstraints + }).then(function(stream) { + let audioTracks = stream.getAudioTracks(); + let videoTracks = stream.getVideoTracks(); + + videoElement.srcObject = stream; + if (audioTracks.length) { + audioTrack = audioTracks[0]; + } + if (videoTracks.length) { + videoTrack = videoTracks[0]; + } + }).then(function() { + new Promise(function(resolve) { + videoElement.onloadedmetadata = resolve; + }); + }).then(function() { + getCurrentSettings(); + }).catch(handleError); +} +</pre> + +<p>ここには、次のようないくつかの手順があります。</p> + +<ol> + <li><code>buildConstraints()</code> を呼び出して、編集ボックス内のコードから2つのトラックの {{domxref("MediaTrackConstraints")}} オブジェクトを作成します。</li> + <li>{{domxref("MediaDevices.getUserMedia", "navigator.mediaDevices.getUserMedia()")}} を呼び出し、動画トラックおよび音声トラックの制約オブジェクトを渡します。 これにより、入力に一致するソースからの音声と動画を含む {{domxref("MediaStream")}} が返されます(通常はウェブカメラですが、適切な制約を指定すると他のソースからメディアを取得できます)。</li> + <li>ストリームを取得したら、画面に表示されるように {{HTMLElement("video")}} 要素に添付し、音声トラックと動画トラックを変数 <code>audioTrack</code> と <code>videoTrack</code> に取り込みます。</li> + <li>次に、動画要素で {{event("onloadedmetadata")}} イベントが発生したときに解決する promise を設定します。</li> + <li>それが起こると、動画の再生を開始したことがわかるので、<code>getCurrentSettings()</code> 関数(上記を参照)を呼び出して、制約とハードウェアの能力を考慮した後にブラウザーが決定した実際の設定を表示します。</li> + <li>エラーが発生した場合は、この記事のもっと下で説明する <code>handleError()</code> メソッドを使用してログに記録します。</li> +</ol> + +<p>また、[動画の開始] ボタンがクリックされるのを監視するイベントリスナーを設定する必要があります。</p> + +<pre class="brush: js">document.getElementById("startButton").addEventListener("click", function() { + startVideo(); +}, false); +</pre> + +<h4 id="Applying_constraint_set_updates" name="Applying_constraint_set_updates">制約セットの更新の適用</h4> + +<p>次に、[制約の適用] ボタンのイベントリスナーを設定します。 クリックされ、まだ使用中のメディアがない場合は、<code>startVideo()</code> を呼び出し、指定された設定でストリームを開始する機能をその関数に処理させます。 それ以外の場合は、次の手順に従って、更新済みの制約を既にアクティブなストリームに適用します。</p> + +<ol> + <li><code>buildConstraints()</code> を、音声トラック(<code>audioConstraints</code>)および動画トラック(<code>videoConstraints</code>)の更新された {{domxref("MediaTrackConstraints")}} オブジェクトを構築するために呼び出します。</li> + <li>{{domxref("MediaStreamTrack.applyConstraints()")}} を、新しい <code>videoConstraints</code> を適用するために動画トラック(存在する場合)で呼び出します。 これが成功したら、動画トラックの現在の設定ボックスの内容を、{{domxref("MediaStreamTrack.getSettings", "getSettings()")}} メソッドを呼び出した結果に基づいて更新します。</li> + <li>それが完了すると、新しい音声制約を適用するために、<code>applyConstraints()</code> を音声トラック(存在する場合)で呼び出します。 これが成功したら、音声トラックの現在の設定ボックスの内容を、{{domxref("MediaStreamTrack.getSettings", "getSettings()")}} メソッドを呼び出した結果に基づいて更新しす。</li> + <li>いずれかの制約セットを適用してエラーが発生した場合、<code>handleError()</code> を使用してメッセージをログに出力します。</li> +</ol> + +<pre class="brush: js">document.getElementById("applyButton").addEventListener("click", function() { + if (!videoTrack && !audioTrack) { + startVideo(); + } else { + buildConstraints(); + if (videoTrack) { + videoTrack.applyConstraints(videoConstraints).then(function() { + videoSettingsText.value = JSON.stringify(videoTrack.getSettings(), null, 2); + }).catch(handleError); + } + + if (audioTrack) { + audioTrack.applyConstraints(audioConstraints).then(function() { + audioSettingsText.value = JSON.stringify(audioTrack.getSettings(), null, 2); + }).catch(handleError); + } + } +}, false); +</pre> + +<h4 id="Handling_the_stop_button" name="Handling_the_stop_button">停止ボタンの処理</h4> + +<p>次に、[動画の停止] ボタンのハンドラーを設定します。</p> + +<pre class="brush: js">document.getElementById("stopButton").addEventListener("click", function() { + if (videoTrack) { + videoTrack.stop(); + } + if (audioTrack) { + audioTrack.stop(); + } + + videoTrack = audioTrack = null; + videoElement.srcObject = null; +}); +</pre> + +<p>これは単にアクティブなトラックを停止し、<code>videoTrack</code> 変数と <code>audioTrack</code> 変数を <code>null</code> に設定してそれらがなくなったことがわかるようにし、{{domxref("HTMLMediaElement.srcObject")}} を <code>null</code> に設定して {{HTMLElement("video")}} 要素からストリームを取り除きます。</p> + +<h4 id="Simple_tab_support_in_the_editor" name="Simple_tab_support_in_the_editor">エディターでの単純な <kbd>tab</kbd> のサポート</h4> + +<p>このコードは、いずれかの制約編集ボックスがフォーカスされているときに <kbd>tab</kbd> キーで2つのスペース文字を挿入することにより、{{HTMLElement("textarea")}} 要素に <kbd>tab</kbd> の単純なサポートを追加します。</p> + +<pre class="brush: js">function keyDownHandler(event) { + if (event.key == "Tab") { + let elem = event.target; + let str = elem.value; + + let position = elem.selectionStart; + let newStr = str.substring(0, position) + " " + + str.substring(position, str.length); + elem.value = newStr; + elem.selectionStart = elem.selectionEnd = position + 2; + event.preventDefault(); + } +} + +videoConstraintEditor.addEventListener("keydown", keyDownHandler, false); +audioConstraintEditor.addEventListener("keydown", keyDownHandler, false); +</pre> + +<h4 id="Show_constrainable_properties_the_browser_supports" name="Show_constrainable_properties_the_browser_supports">ブラウザーがサポートする制約可能なプロパティの表示</h4> + +<p>パズルの最後の重要な部分: ユーザーの参照用に、ブラウザーがサポートする制約可能なプロパティのリストを表示するコード。 各プロパティは、ユーザーの利便性のために MDN のドキュメントへのリンクです。 このコードの動作の詳細については、<a href="/ja/docs/Web/API/MediaDevices/getSupportedConstraints#Example"><code>MediaDevices.getSupportedConstraints()</code> の例</a>を参照してください。</p> + +<div class="note"> +<p>もちろん、このリストには非標準のプロパティが含まれている場合があります。 その場合、ドキュメントのリンクはあまり役に立たないでしょう。</p> +</div> + +<pre class="brush: js">let supportedConstraints = navigator.mediaDevices.getSupportedConstraints(); +for (let constraint in supportedConstraints) { + if (supportedConstraints.hasOwnProperty(constraint)) { + let elem = document.createElement("li"); + + elem.innerHTML = "<code><a href='https://developer.mozilla.org/docs/Web/API/MediaTrackSupportedConstraints/" + .concat(constraint) + "' target='_blank'>" + constraint + "</a></code>"; + supportedConstraintList.appendChild(elem); + } +} +</pre> + +<h4 id="Error_handling" name="Error_handling">エラー処理</h4> + +<p>また、いくつかの簡単なエラー処理コードがあります。 <code>handleError()</code> は失敗したプロミスを処理するために呼び出され、<code>log()</code> 関数は動画の下の特別なロギング {{HTMLElement("div")}} ボックスにエラーメッセージを追加します。</p> + +<pre class="brush: js">function log(msg) { + logElement.innerHTML += (msg + "<br>"); +} + +function handleError(reason) { + log("Error <code>" + reason.name + + "</code> in constraint <code>" + reason.constraint + + "</code>: " + reason.message); +}</pre> + +<h3 id="Result" name="Result">結果</h3> + +<p>ここで、実際の完全な例を見ることができます。</p> + +<p>{{EmbedLiveSample("Example_Constraint_exerciser", 650, 800, "", "", "", "microphone; camera")}}</p> + +<h2 id="Specifications" name="Specifications">仕様</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">仕様</th> + <th scope="col">状態</th> + <th scope="col">コメント</th> + </tr> + <tr> + <td>{{SpecName('Media Capture', '#constrainable-interface', 'Constrainable pattern')}}</td> + <td>{{Spec2('Media Capture')}}</td> + <td>初期定義</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> + +<h3 id="MediaDevices.getSupportedConstraints" name="MediaDevices.getSupportedConstraints"><code>MediaDevices.getSupportedConstraints</code></h3> + +<div> + + +<p>{{Compat("api.MediaDevices.getSupportedConstraints")}}</p> +</div> + +<h2 id="See_also" name="See_also">関連情報</h2> + +<ul> + <li><a href="/ja/docs/Web/API/Media_Streams_API">Media Capture and Streams API</a></li> + <li>{{domxref("MediaTrackCapabilities")}}</li> + <li>{{domxref("MediaTrackConstraints")}}</li> + <li>{{domxref("MediaTrackSettings")}}</li> + <li>{{domxref("MediaDevices.getSupportedConstraints()")}}</li> + <li>{{domxref("MediaStreamTrack.applyConstraints()")}}</li> + <li>{{domxref("MediaStreamTrack.getSettings()")}}</li> +</ul> diff --git a/files/ja/web/api/media_streams_api/index.html b/files/ja/web/api/media_streams_api/index.html new file mode 100644 index 0000000000..ed658b728c --- /dev/null +++ b/files/ja/web/api/media_streams_api/index.html @@ -0,0 +1,131 @@ +--- +title: Media Capture and Streams API (Media Streams) +slug: Web/API/Media_Streams_API +tags: + - API + - Advanced + - Audio + - Guide + - Introduction + - Media + - Media Capture and Streams API + - Media Streams API + - NeedsContent + - Video +translation_of: Web/API/Media_Streams_API +--- +<div>{{DefaultAPISidebar("Media Capture and Streams")}}</div> + +<p><strong>Media Capture and Streams</strong> APIは一般的に<em>Media Stream API</em>や<em>Stream API</em>と呼ばれる<a href="/en-US/docs/WebRTC" title="/en-US/docs/WebRTC">WebRTC</a>に関連したAPIです。このAPIでは、オーディオやビデオデータのストリーム、これらを操作するためのメソッド、データタイプに関連づけられた制約、データを非同期に利用する際の成功と失敗のコールバック、これらの処理を行なっている最中に発生するイベントなどをサポートします。</p> + +<h2 id="基本概念">基本概念</h2> + +<p>このAPIは、オーディオまたはビデオに関連づけられたデータの流れを表現するための{{domxref("MediaStream")}}オブジェクトの操作を基本としています。例として<a href="/en-US/docs/WebRTC/taking_webcam_photos#Get_the_video" title="/en-US/docs/WebRTC/taking_webcam_photos#Get_the_video">Get the video</a>(英語)をご覧ください。</p> + +<p><code>MediaStream</code>は0個以上の{{domxref("MediaStreamTrack")}}によって構成されます。<code>MediaStreamTrack</code>は様々なオーディオやビデオの<strong>トラック</strong>を表現します。それぞれの<code>MediaStreamTrack</code>は、1つ以上の<strong>チャンネル</strong>を持ちます。このチャンネルはメディアストリームの最小の単位を表現します。例えば、ステレオのオーディオトラックの<em>left</em>と<em>right</em>のチャンネルのそれぞれのように、与えられたスピーカーに関連づけられたオーディオ信号です。</p> + +<p><code>MediaStream</code>オブジェクトは、1つの<strong>入力</strong>と1つの<strong>出力</strong>を持ちます。<code>MediaStream</code>オブジェクトは、ローカルで呼び出される{{domxref("MediaDevices.getUserMedia", "getUserMedia()")}}によって生成され、ユーザーのカメラやマイクの1つを入力ソースとして持ちます。ローカルでない<code>MediaStream</code>は、{{HTMLElement("video")}}や{{HTMLElement("audio")}}などのメディア要素や、WebRTC {{domxref("RTCPeerConnection")}} APIによって取得できるネットワーク越しに生成されたストリーム、<a href="/en-US/docs/Web_Audio_API" title="/en-US/docs/Web_Audio_API">Web Audio API</a> {{domxref("MediaStreamAudioSourceNode")}}によって作成されたストリームとして表現されます。<code>MediaStream</code>オブジェクトの出力は<strong>コンシューマ</strong>(consumer)に接続されます。出力として{{HTMLElement("audio")}}や{{HTMLElement("video")}}などのメディア要素、WebRTC {{domxref("RTCPeerConnection")}} API、<a href="/en-US/docs/Web_Audio_API" title="/en-US/docs/Web_Audio_API">Web Audio API</a> {{domxref("MediaStreamAudioDestinationNode")}}が使用できます。</p> + +<p> </p> + +<h2 id="リファレンス">リファレンス</h2> + +<div class="index"> +<ul> + <li>{{event("addtrack")}} (event)</li> + <li>{{domxref("AudioStreamTrack")}}</li> + <li>{{domxref("BlobEvent")}}</li> + <li>{{event("ended")}} (event)</li> + <li>{{domxref("MediaStream")}}</li> + <li>{{domxref("MediaStreamConstraints")}}</li> + <li>{{domxref("MediaStreamEvent")}}</li> + <li>{{domxref("MediaStreamTrack")}}</li> + <li>{{domxref("MediaStreamTrackEvent")}}</li> + <li>{{domxref("MediaTrackCapabilities")}}</li> + <li>{{domxref("MediaTrackConstraints")}}</li> + <li>{{domxref("MediaTrackSettings")}}</li> + <li>{{domxref("MediaTrackSupportedConstraints")}}</li> + <li>{{event("muted")}} (event)</li> + <li>{{domxref("NavigatorUserMedia")}}</li> + <li>{{domxref("NavigatorUserMediaError")}}</li> + <li>{{event("overconstrained")}} (event)</li> + <li>{{event("removetrack")}} (event)</li> + <li>{{event("started")}} (event)</li> + <li>{{event("unmuted")}} (event)</li> + <li>{{domxref("URL")}}</li> + <li>{{domxref("VideoStreamTrack")}}</li> +</ul> +</div> + +<h2 id="ガイドとチュートリアル">ガイドとチュートリアル</h2> + +<p>{{LandingPageListSubpages}}</p> + +<h2 id="ブラウザ互換性">ブラウザ互換性</h2> + +<p>{{ CompatibilityTable }} </p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Edge</th> + <th>Internet Explorer</th> + <th>Opera </th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Stream API </td> + <td>21{{ property_prefix("webkit") }} </td> + <td>Nightly 18{{ property_prefix("moz") }} </td> + <td>{{ CompatVersionUnknown }}</td> + <td>{{ CompatUnknown }} </td> + <td>12</td> + <td>11</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Stream API </td> + <td>{{ CompatNo }} </td> + <td>{{CompatVersionUnknown}}</td> + <td>{{ CompatUnknown }}</td> + <td>{{ CompatUnknown }} </td> + <td>{{ CompatNo }} </td> + <td>11.2</td> + </tr> + </tbody> +</table> +</div> + +<p>現在、ChromeとOpera、Firefox Nightly 18でカメラへアクセスするためにWebRTCを用いることができます。Firefox NightlyでWebRTCを有効にするには、次の設定でフラグを有効にする必要があります。</p> + +<ul> + <li>アドレスバーに"about:config"を入力して、変更を許可してください。</li> + <li>"media.navigator.enabled"の項目を探して、trueを設定してください。</li> +</ul> + +<h2 id="関連項目">関連項目</h2> + +<ul> + <li><a href="/en-US/docs/WebRTC" title="/en-US/docs/WebRTC">WebRTC</a> - APIの入門ページ</li> + <li>{{domxref("mediaDevices.getUserMedia()")}}</li> + <li><a href="/en-US/docs/WebRTC/taking_webcam_photos">Taking webcam photos</a>: <code>getUserMedia()</code>を用いたデモとチュートリアル</li> +</ul> |
