StyleSheet.title - Web API

StyleSheet.title
================

**`title`** は `StyleSheet` インターフェイスのプロパティで、現在のスタイルシートのアドバイザリータイトルを返します。

タイトルは、よく `ownerNode` で指定されています。

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-stylesheet-title |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


StyleSheet.media - Web API

StyleSheet.media
================

**`media`** は `StyleSheet` インターフェイスのプロパティで、スタイル情報の対象となる出力先メディアを指定します。これは読み取り専用の配列風の `MediaList` オブジェクトで、 `deleteMedium()` で削除し、 `appendMedium()` で追加することが可能です。

値
-

読み取り専用、配列風の `MediaList` オブジェクトです。

例
-

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Test page</title>
    <link rel="stylesheet" href="document.css" media="screen" />
    <style rel="stylesheet" media="screen, print">
 body {
 background-color: snow;
 }
 </style>
  </head>
  <body>
    <script>
 for (let i = 0; i < document.styleSheets.length; i++) {
 console.log(
 `document.styleSheets[${i}].media: ${JSON.stringify(
 document.styleSheets[i].media,
 )}`,
 );
 if (iSheetIndex === 0)
 document.styleSheets[i].media.appendMedium("handheld");
 if (iSheetIndex === 1)
 document.styleSheets[i].media.deleteMedium("print");
 console.log(
 `document.styleSheets[${i}].media: ${JSON.stringify(
 document.styleSheets[i].media,
 )}`,
 );
 }
 // This will log:
 // document.styleSheets[0].media: {"0":"screen"}
 // document.styleSheets[0].media: {"0":"screen","1":"handheld"}
 // document.styleSheets[1].media: {"0":"screen","1":"print"}
 // document.styleSheets[1].media: {"0":"screen"}
 </script>
  </body>
</html>
```

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-stylesheet-media |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


StyleSheet.parentStyleSheet - Web API

StyleSheet.parentStyleSheet
===========================

**`parentStyleSheet`** は `StyleSheet` インターフェイスのプロパティで、指定されたスタイルシートをインクルードしている場合、そのスタイルシートを返します。

値
-

`StyleSheet` オブジェクトです。

例
-

```js
// 最上位のスタイルシートを探す
const sheet = stylesheet.parentStyleSheet ?? stylesheet;
```

メモ
--

対象スタイルシートが最上位のスタイルシートの場合、または対象スタイルシートがインクルードに対応していない場合、返値は `null` となります。

仕様書
---

| Specification |
| --- |
| CSS Object Model (CSSOM) # dom-stylesheet-parentstylesheet |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


SpeechRecognitionAlternative.transcript - Web API

SpeechRecognitionAlternative.transcript
=======================================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

`SpeechRecognitionResult` (en-US) インターフェースの **`transcript`** 読み取り専用プロパティは、認識したワードの記録を含む文字列を返します。

連続認識において、連続した `SpeechRecognitionResult` (en-US) の連結がセッションの適切な記録を生成するように、必要に応じて先頭または末尾の空白が含まれます。

構文
--
```

var myTranscript = speechRecognitionAlternativeInstance.transcript;
```

### 戻り値

`DOMString`。

例
-

このコードは、Speech color changer から抜き出しています。

```js
recognition.onresult = function (event) {
  // The SpeechRecognitionEvent results property returns a SpeechRecognitionResultList object
  // The SpeechRecognitionResultList object contains SpeechRecognitionResult objects.
  // It has a getter so it can be accessed like an array
  // The first [0] returns the SpeechRecognitionResult at position 0.
  // Each SpeechRecognitionResult object contains SpeechRecognitionAlternative objects that contain individual results.
  // These also have getters so they can be accessed like arrays.
  // The second [0] returns the SpeechRecognitionAlternative at position 0.
  // We then return the transcript property of the SpeechRecognitionAlternative object
  var color = event.results[0][0].transcript;
  diagnostic.textContent = "Result received: " + color + ".";
  bg.style.backgroundColor = color;
};
```

仕様
--

| Specification |
| --- |
| Web Speech API # dom-speechrecognitionalternative-transcript |

ブラウザー実装状況
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

* [1] Chrome では、SpeechRecognitionare インターフェースにプレフィックスが必要です。そのため、インターフェース名に `webkitSpeechRecognition` のようなプレフィックスが必要です; また、認識を動作させるには、Web サーバ上から提供する必要があります。
* [2]
 about:config
 の `media.webspeech.recognition.enable` フラグで有効にできますが、現在の音声認識はデスクトップ版の Firefox では機能しません - 必要な内部権限が整理されればすぐに適切に公開されます。
### Firefox OS 許可

アプリで音声認識を使用するには、manifest で次の許可が必要です:

```json
"permissions": {
  "audio-capture" : {
    "description" : "Audio capture"
  },
  "speech-recognition" : {
    "description" : "Speech recognition"
  }
}
```

特権アプリも必要なため、次のものも含める必要があります。

```json
  "type": "privileged"
```

関連項目
----

* Web Speech API


TextTrackCue.endTime - Web API

TextTrackCue.endTime
====================

**`endTime`** は `TextTrackCue` インターフェイスのプロパティで、キューの終了時刻を返したり設定したりします。

値
-

数値で、終了時刻を秒単位で表します。

例
-

以下の例では、 0.1 秒から始まり 0.9 秒で終わる新しい `VTTCue` （`TextTrackCue` を継承したもの）が作成されます。そして、 `endTime` プロパティがコンソールに表示されます。

```js
let video = document.querySelector("video");
let track = video.addTextTrack("captions", "Captions", "en");
track.mode = "showing";

let cue1 = new VTTCue(0.1, 0.9, "Hildy!");
console.log(cue1.endTime); // 0.9
track.addCue(cue1);
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-texttrackcue-endtime |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue: exit イベント - Web API

TextTrackCue: exit イベント
=======================

**`exit`** イベントは、キューがアクティブでなくなったときに発行されます。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("exit", (event) => {});

onexit = (event) => {};
```

イベント型
-----

一般的な `Event` で、追加のプロパティはありません。

例
-

以下の例では、 `cue1` がアクティブなキューとして表示されなくなったときに、コンソールに表示されます。

```js
cue1.addEventListener("enter", (event) => {
  console.log("Cue 1 has left the building.");
});
```

仕様書
---

| Specification |
| --- |
| HTML Standard # event-media-exit |
| HTML Standard # handler-texttrackcue-onexit |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue.pauseOnExit - Web API

TextTrackCue.pauseOnExit
========================

**`pauseOnExit`** は `TextTrackCue` インターフェイスのプロパティで、このキューが適用される範囲の終わりに達したとき、メディアの再生を一時停止すべきかどうかを示すフラグを返したり設定したりします。

値
-

論理値で、 true ならばメディアが一時停止します。

例
-

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-texttrackcue-pauseonexit |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue.id - Web API

TextTrackCue.id
===============

**`id`** は `TextTrackCue` インターフェイスのプロパティで、このキューの識別子を返したり設定したりします。

値
-

このキューの ID を持つ文字列です。

例
-

以下の例では、新しい `VTTCue` （`TextTrackCue` を継承したもの）が作成されます。そして、キューを追加する前に、 `id` プロパティを "first" に設定しています。

```js
let video = document.querySelector("video");
let track = video.addTextTrack("captions", "Captions", "en");
track.mode = "showing";

let cue1 = new VTTCue(0, 0.9, "Hildy!");
cue1.id = "first";
track.addCue(cue1);
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-texttrackcue-id |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue.track - Web API

TextTrackCue.track
==================

**`track`** は `TextTrackCue` インターフェイスの読み取り専用プロパティで、このキューが所属する `TextTrack` オブジェクトを返します。

値
-

`TextTrack` オブジェクトです。

例
-

以下の例では、新しい `VTTCue` （`TextTrackCue` を継承）を作成し、それをトラックに追加しています。 `track` の値はコンソールに表示されます。

```js
let video = document.querySelector("video");
let captiontrack = video.addTextTrack("captions", "Captions", "en");
captiontrack.mode = "showing";

let cue1 = new VTTCue(0, 0.9, "Hildy!");
captiontrack.addCue(cue1);
console.log(cue1.track); // a TextTrack object.
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-texttrackcue-track |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue.startTime - Web API

TextTrackCue.startTime
======================

**`startTime`** は `TextTrackCue` インターフェイスのプロパティで、このキューの開始時刻を返したり設定したりします。

値
-

数値で、開始時刻を秒単位で表します。

例
-

以下の例では、 0.1 秒から始まり 0.9 秒で終わる新しい `VTTCue` （`TextTrackCue` を継承したもの）が作成されます。そして、 `startTime` プロパティがコンソールに表示されます。

```js
let video = document.querySelector("video");
let track = video.addTextTrack("captions", "Captions", "en");
track.mode = "showing";

let cue1 = new VTTCue(0.1, 0.9, "Hildy!");
console.log(cue1.startTime); // 0.1
track.addCue(cue1);
```

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-texttrackcue-starttime |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextTrackCue: enter イベント - Web API

TextTrackCue: enter イベント
========================

**`enter`** イベントは、キューがアクティブになったときに発行されます。字幕やキャプションの場合、メディア上に表示されるタイミングです。

構文
--

このイベント名を `addEventListener()` などのメソッドで使用するか、イベントハンドラープロパティを設定するかしてください。

```js
addEventListener("enter", (event) => {});

onenter = (event) => {};
```

イベント型
-----

一般的な `Event` で、追加のプロパティはありません。

例
-

以下の例では、`cue1` がアクティブキューになったときにコンソールに表示します。

```js
cue1.addEventListener("enter", (event) => {
  console.log("Cue 1 has displayed");
});
```

仕様書
---

| Specification |
| --- |
| HTML Standard # event-media-enter |
| HTML Standard # handler-texttrackcue-onenter |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


AudioWorkletProcessor: port プロパティ - Web API

AudioWorkletProcessor: port プロパティ
=================================

`AudioWorkletProcessor` インターフェイスの読み取り専用プロパティ **`port`** は、関連付けられた `MessagePort` を返します。これは、処理器と対応する `AudioWorkletNode` の間の通信に使用できます。

**メモ:** チャネルのもう一方の端は、ノードの `port` プロパティから参照できます。

値
-

`AudioWorkletProcessor` と対応する `AudioWorkletNode` を接続する `MessagePort` オブジェクトです。

例
-

`AudioWorkletNode.port` にサンプルコードがあります。

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audioworkletprocessor-port |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* ウェブオーディオ API
* Web Audio API の使用


AudioWorkletProcessor: AudioWorkletProcessor() コンストラクター - Web API

AudioWorkletProcessor: AudioWorkletProcessor() コンストラクター
=======================================================

**`AudioWorkletProcessor()`** コンストラクターは新しい `AudioWorkletProcessor` オブジェクトを生成します。このオブジェクトは `AudioWorkletNode` で用いる音声処理の仕組みを表します。

構文
--

**メモ:** `AudioWorkletProcessor` とその派生クラスは、ユーザーのコードから直接生成することはできません。これらは対応する `AudioWorkletNode` の生成に伴って内部でのみ生成されます。

```js
new AudioWorkletProcessor(options)
```

### 引数

`options`

`AudioWorkletNode のコンストラクター` の引数 `options` に渡されたオブジェクトです。構造化複製アルゴリズムを経由して渡されます。
 以下のプロパティが利用できます。

`numberOfInputs` 省略可

`numberOfInputs` プロパティを初期化する値です。デフォルト値は 1 です。

`numberOfOutputs` 省略可

`numberOfOutputs` プロパティを初期化する値です。デフォルト値は 1 です。

`outputChannelCount` 省略可

それぞれの出力のチャンネル数を決める **配列** です。たとえば、`outputChannelCount: [n, m]` は最初の出力のチャンネル数を `n` に、2 番目の出力のチャンネル数を `m` に設定します。配列の長さは `numberOfOutputs` に一致しなければなりません。

`parameterData` 省略可

このノード (の `parameters` プロパティ) の独自の `AudioParam` オブジェクトの初期値が入ったオブジェクトです。キーを独自プロパティの名前、値を初期値とします。

`processorOptions` 省略可

用いる `AudioWorkletProcessor` の独自の初期化に用いる任意の追加データです。

なお、最初の 2 個のプロパティにはデフォルト値があるので、`AudioWorkletNode のコンストラクター` に `options` オブジェクトが渡されなかった場合でも、ノードから `AudioWorkletProcessor` のコンストラクターには `options` オブジェクトが渡され、このオブジェクトには少なくとも `numberOfInputs` と `numberOfOutputs` があります。

### 返値

新しく構築された `AudioWorkletProcessor` のインスタンスを返します。

例
-

この例では、`AudioWorkletNode constructor` に独自のオプションを渡し、その構造化複製が `AudioWorkletProcessor` のコンストラクターに渡される様子を観察します。

 まず、独自の `AudioWorkletProcessor` を定義して登録する必要があります。
 これは別のファイルで行うことに注意してください。

```js
// test-processor.js
class TestProcessor extends AudioWorkletProcessor {
  constructor(options) {
    super();
    console.log(options.numberOfInputs);
    console.log(options.processorOptions.someUsefulVariable);
  }
  process(inputs, outputs, parameters) {
    return true;
  }
}

registerProcessor("test-processor", TestProcessor);
```

次に、メインスクリプトファイルで処理器をロードし、この処理器の名前と `options` オブジェクトを渡して `AudioWorkletNode` のインスタンスを生成します。

`options` オブジェクトでは、`someUsefulVariable` キーに `Map` のインスタンスを入れた `processorOptions` を渡します。`numberOfInputs` は渡さず、デフォルト値が設定される様子を観察します。

```js
const audioContext = new AudioContext();
await audioContext.audioWorklet.addModule("test-processor.js");
const testNode = new AudioWorkletNode(audioContext, "test-processor", {
  processorOptions: {
    someUsefulVariable: new Map([
      [1, "one"],
      [2, "two"],
    ]),
  },
});
```

コンソールに以下のように出力されます。
```

> 1 // AudioWorkletNode options.numberOfInputs はデフォルトに設定される
> Map(2) { 1 => "one", 2 => "two" } // someUsefulVariable で設定した Map の複製
```

仕様書
---

| Specification |
| --- |
| Web Audio API # dom-audioworkletprocessor-audioworkletprocessor |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `AudioWorkletNode` インターフェイス


AudioWorkletProcessor: process() メソッド - Web API

AudioWorkletProcessor: process() メソッド
=====================================

`AudioWorkletProcessor` の派生クラスの **`process()`** メソッドは、音声処理器ワークレットの音声処理アルゴリズムを実装します。

このメソッドは `AudioWorkletProcessor` インターフェイスには含まれていませんが、`AudioWorkletProcessor` の実装はすべて `process()` メソッドを用意しなければいけません。

 このメソッドは、処理器の対応する `AudioWorkletNode` に音声ブロック (rendering quantum とも呼ばれる) が送られてくるたびに、音声レンダリングスレッドから同期で呼ばれます。
 すなわち、新しい音声ブロックが処理器で処理可能になるたびに、処理をするために `process()` 関数が呼ばれます。

**メモ:** 現在、音声データブロックの長さは常に 128 フレームです。すなわち、入力のそれぞれのチャンネルについて 128 個の 32 ビット浮動小数点数のサンプルが格納されています。しかし、この仕様を変更し、状況に応じて (たとえば、音声ハードウェアや CPU の使用の効率がブロックサイズを大きくすると上がる場合) 音声ブロックのサイズを変えることができるようにする計画がすでに進行中です。このため、特定のサイズを仮定するのではなく、*常にサンプル配列のサイズをチェックしなければなりません。*

このサイズは時間とともに変わることも許される可能性があるので、最初のブロックだけを見てサンプルバッファーのサイズが常に同じだと仮定してはいけません。

構文
--

```js
process(inputs, outputs, parameters)
```

### 引数

`inputs`

ノードに接続されている *入力* の配列です。この配列のそれぞれの要素は *チャンネル* の配列です。それぞれの *チャンネル* は 128 個のサンプルが入った `Float32Array` です。たとえば、`inputs[n][m][i]` は `n` 番目の入力の `m` 番目のチャンネルの `i` 番目のサンプルにアクセスします。

それぞれのサンプルの値は `[-1 .. 1]` の範囲です。

*入力* の数、そしてそれを反映したこの配列の長さはノードの生成時に固定されます。(`AudioWorkletNode` を参照してください) ノードの `n` 番目の入力に活動中のノードが接続されていない場合は、`inputs[n]` は空の配列になります。(0 個の入力チャンネルが利用可能です)

各入力の *チャンネル* の数は `channelCount` および `channelCountMode` プロパティによって変化する可能性があります。

`outputs`

*出力* の配列で、引数 `inputs` と似た構造です。`process()` メソッドの実行時に値を入れられることを意図しています。各出力チャンネルはゼロで初期化されます。すなわち、出力の配列を変更しない場合は処理器は無音を出力します。

`parameters`

文字列のキーと `Float32Array` の値を持つオブジェクトです。`parameterDescriptors` ゲッターで定義した独自の `AudioParam` それぞれについて、`name` がこのオブジェクトのキーとなり、値が `Float32Array` となります。配列に格納する値は、スケジュールされた自動化イベントを考慮して計算されます。

パラメーターの自動化レートが `"a-rate"` の場合は、配列には 128 個の値が格納され、現在の音声ブロックのそれぞれのフレームに値が 1 個ずつ対応します。現在のブロックが表す時間中に自動化が行われていない場合は、同じ値を 128 個格納するかわりに、ブロック全体で変わらない 1 個の値が格納されることがあります。

自動化レートが `"k-rate"` の場合は、配列には 1 個の値が格納され、この値を 128 個のフレームそれぞれで用います。

### 返値

ユーザーエージェントの内部ロジックがノードをシャットダウンしても安全だと判断しても `AudioWorkletNode` の活動を続けるかを表す `boolean` 値を返します。

この返値により、処理器が `AudioWorkletProcessor` とそれを所有するノードの生存期間ポリシーを制御することができます。ブラウザーが返値とノードの状態に基づいてノードを停止すると判断すると、`process()` は呼ばれなくなります。

`true` を返すことで、ウェブオーディオ API にこのノードの活動を継続させることができます。
 `false` を返すと、新しい音声データの生成も、処理中の入力からのデータの取得もしていないとき、ブラウザーがノードを終了させることができるようになります。

最もよくみられる音声ノードの種類として、以下の 3 種類があります。

1. 出力元。このようなノードを実装している `AudioWorkletProcessor` では、出力を生成している間はずっと `process` メソッドは `true` を返すべきです。もう出力を生成しないということがわかったら、このメソッドはできるだけすぐに `false` を返すべきです。たとえば、`AudioBufferSourceNode` を考えてみましょう。この種類のノードのための処理器は、バッファーの再生中は `process` メソッドは `true` を返し、バッファーの再生が終わったら `false` を返し始めるべきです。(同じ `AudioBufferSourceNode` で再び `play` を呼ぶことはできません)
2. 入力を変換するノード。このようなノードを実装している処理器は、活動中の入力ノードやノードへの参照があるときガベージコレクトの対象にできるかどうかを判断できるようにするため、`process` メソッドは `false` を返すべきです。この挙動をするノードの例は `GainNode` です。接続されている入力が無くなったらすぐ、参照は残っていても、ゲインを適用する対象が無いので、安全にガベージコレクトの対象にできます。
3. 入力を変換するが、*テールタイム* があるノード。すなわち、入力が切断されたり活動を停止 (0 個のチャンネルを生成する) したりした後もしばらくの間出力を生成するノード。このようなノードを実装している処理器は、(入力に含まれるチャンネルが 0 個になるとすぐに始まる) *テールタイム* の間は `process` メソッドは `true` を返すべきです。このようなノードの例は `DelayNode` です。このノードには `delayTime` プロパティに等しい *テールタイム* があります。

**メモ:** `return` 文が無い場合、メソッドは `undefined` を返すことになります。これは偽と解釈される値なので、`false` を返すのと同じ効果があります。
 明示的な `return` 文を省略すると、ノードが見つけにくい問題を起こす可能性があります。

### 例外

`process()` メソッドはユーザーが実装するので、任意の例外を投げることができます。
 補足されないエラーが投げられた場合は、ノードは `processorerror` イベントを生成し、その後ずっと無音を出力します。

例
-

この例では、最初の出力としてホワイトノイズを出力する `AudioWorkletProcessor` を作成します。ゲインは `customGain` パラメーターで制御できます。

```js
class WhiteNoiseProcessor extends AudioWorkletProcessor {
  process(inputs, outputs, parameters) {
    // 最初の出力を取得する
    const output = outputs[0];
    // 各チャンネルにランダム値にゲインを掛けたものを入れる
    output.forEach((channel) => {
      for (let i = 0; i < channel.length; i++) {
        // 各サンプル用のランダム値を生成する
        // Math.random の値域は [0; 1) だが、ここでは [-1; 1] が欲しい
        // 1 ちょうどにはならないが、簡単のためここではよい
        channel[i] =
          (Math.random() \* 2 - 1) \*
          // この配列には、自動化が進行中か、
          // そして自動化レートが k-rate なのか a-rate なのかにより、
          // 1 個または 128 個の値が格納されている
          (parameters["customGain"].length > 1
            ? parameters["customGain"][i]
            : parameters["customGain"][0]);
      }
    });
    // これは自身で出力を生成する音源ノードなので、
    // メインスレッドから参照されていなくても、
    // 間違ってガベージコレクトされないように true を返す
    return true;
  }
  // process メソッドで用いる customGain パラメーターを定義する
  static get parameterDescriptors() {
    return [
      {
        name: "customGain",
        defaultValue: 1,
        minValue: 0,
        maxValue: 1,
        automationRate: "a-rate",
      },
    ];
  }
}
```

仕様書
---

| Specification |
| --- |
| Web Audio API # process |

ブラウザーの互換性
---------

これはブラウザーが提供するメソッドではなく、クライアントコードで書く必要があるコールバックメソッドです。

関連情報
----

* Web Audio API の使用


CSSTransformValue() - Web API

CSSTransformValue()
===================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`CSSTransformValue()`** コンストラクターは、個々の座標変換オブジェクトのリストを表す、新しい `CSSTransformValue` オブジェクトを作成します。

構文
--

```js
new CSSTransformValue(transforms)
```

### 引数

`transforms`

反復処理を行う `CSSTransformComponent` オブジェクトのリスト

### 返値

新しい `CSSTransformValue` です。

### 例外

`TypeError`

transforms が空の場合に発生します。

例
-

To do

仕様書
---

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-csstransformvalue-csstransformvalue |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.values() - Web API

CSSTransformValue.values()
==========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`CSSTransformValue.values()`** は、 CSSTransformValue オブジェクトの各位置に対応する値を格納した新しい *配列イテレーター* オブジェクトを返します。

構文
--

```js
values()
```

### 引数

なし。

### 返値

新しい `Array` です。

例
-

To Do

仕様書
---

#### No specification found

No specification data found for `api.CSSTransformValue.values`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.length - Web API

CSSTransformValue.length
========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`length`** は `CSSTransformValue` インターフェイスの読み取り専用プロパティで、リスト中の座標変換コンポーネントの数を返します。

値
-

リスト内の座標変換コンポーネントの数を表す整数です。

例
-

To Do

仕様書
---

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-csstransformvalue-length |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.entries() - Web API

CSSTransformValue.entries()
===========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`CSSTransformValue.entries()`** メソッドは、指定されたオブジェクト自身で列挙可能なプロパティ `[key, value]`のペアを `for...in` ループによって提供されるのと同じ順序の配列で返します（違いは for-in ループがプロトタイプチェーンでも同様に列挙するところです）。

構文
--

```js
entries(obj)
```

### 引数

`obj`

自身のプロパティ `[key, value]` の組を列挙して返す `CSSTransformValue` を指定します。

### 返値

指定された `CSSTransformValue` オブジェクト自身の列挙可能なプロパティ `[key, value]` のペアの配列です。

例
-

To Do

仕様書
---

#### No specification found

No specification data found for `api.CSSTransformValue.entries`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.toMatrix() - Web API

CSSTransformValue.toMatrix()
============================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`toMatrix()`** は `CSSTransformValue` インターフェイスのメソッドで、 `DOMMatrix` オブジェクトを返します。

構文
--

```js
toMatrix()
```

### 引数

なし。

### 返値

`DOMMatrix` オブジェクトです。

### 例外

`TypeError`

行列の生成に関わる長さが px と互換性のない単位である場合（例えば相対的な長さやパーセント値など）に発生します。

例
-

To Do

仕様書
---

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-csstransformvalue-tomatrix |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.keys() - Web API

CSSTransformValue.keys()
========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`CSSTransformValue.keys()`** メソッドは、配列の各インデックスに対応するキーを格納した新しい *配列イテレーター* オブジェクトを返します。

構文
--

```js
keys()
```

### 引数

なし。

### 返値

新しい `Array` です。

例
-

To Do

仕様書
---

#### No specification found

No specification data found for `api.CSSTransformValue.keys`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.forEach() - Web API

CSSTransformValue.forEach()
===========================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`CSSTransformValue.forEach()`** メソッドは、指定された関数を `CSSTransformValue` の各要素に対して一度だけ実行します。

構文
--

```js
// アロー関数
forEach((currentValue) => { /\* … \*/ } )
forEach((currentValue, index) => { /\* … \*/ } )
forEach((currentValue, index, array) => { /\* … \*/ } )

// コールバック関数
forEach(callbackFn)
forEach(callbackFn, thisArg)

// インラインコールバック関数
forEach(function(currentValue) { /\* … \*/ })
forEach(function(currentValue, index) { /\* … \*/ })
forEach(function(currentValue, index, array) { /\* … \*/ })
forEach(function(currentValue, index, array) { /\* … \*/ }, thisArg)
```

### 引数

`callbackFn`

各要素に対して実行する関数で、3 つの引数を取ります。

`currentValue`

現在処理中の要素の値です。

`index` 省略可

現在処理中の要素の位置です。

`array` 省略可

`forEach()` が実行されている `CSSTransformValue` です。

`thisArg` 省略可

`callback` が実行されるときに **`this`** として扱われる値（すなわち、 `Object` の参照）です。

### 返値

なし (`undefined`)。

例
-

To Do

仕様書
---

#### No specification found

No specification data found for `api.CSSTransformValue.forEach`.
Check for problems with this page or contribute a missing `spec_url` to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


CSSTransformValue.is2D - Web API

CSSTransformValue.is2D
======================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`is2D`** は `CSSTransformValue` インターフェイスの読み取り専用プロパティで、この座標変換が 2D であるか 3D であるかを返します。

`CSSTransformValue` の場合、個々の関数のいずれかが `Is2D` で false を返す場合は false を返し、このプロパティは true を返します。

値
-

論理値です。true はその座標変換が 2D 変換であることを示し、 false は 3D 変換であることを示します。

例
-

To Do

仕様書
---

| Specification |
| --- |
| CSS Typed OM Level 1 # dom-csstransformvalue-is2d |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


GamepadEvent: GamepadEvent() コンストラクター - Web API

GamepadEvent: GamepadEvent() コンストラクター
=====================================

**`GamepadEvent()`** コンストラクターは、新しい `GamepadEvent` オブジェクトを作成します。

構文
--

```js
new GamepadEvent(type, options)
```

### 引数

`type`

 このイベントの名前の文字列です。
 大文字小文字を区別し、ブラウザーは `gamepadconnected` または `gamepaddisconnected` に設定します。

`options`

オブジェクトで、*`Event()` で定義されたプロパティに加え*、以下のプロパティを持つことができます。

`gamepad`

このイベントに関連付けられたゲームパッドを記述する `Gamepad` オブジェクトです。

### 返値

新しい `GamepadEvent` オブジェクトです。

仕様書
---

| Specification |
| --- |
| Gamepad # dom-gamepadevent-constructor |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


GamepadEvent: gamepad プロパティ - Web API

GamepadEvent: gamepad プロパティ
===========================

**`GamepadEvent.gamepad`** は **`GamepadEvent` インターフェイス**のプロパティで、`Gamepad` オブジェクトを返し、発生した `gamepadconnected` イベントと `gamepaddisconnected` イベントの関連するゲームパッドデータへのアクセスを提供します。

値
-

`Gamepad` オブジェクトです。

例
-

`gamepad` プロパティが `gamepadconnected` イベントが発生して呼び出されているところです。

```js
window.addEventListener("gamepadconnected", (e) => {
  console.log(
    "Gamepad connected at index %d: %s. %d buttons, %d axes.",
    e.gamepad.index,
    e.gamepad.id,
    e.gamepad.buttons.length,
    e.gamepad.axes.length,
  );
});
```

仕様書
---

| Specification |
| --- |
| Gamepad # dom-gamepadevent-gamepad |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

ゲームパッド API の使用


WebRTC 接続 - Web API

WebRTC 接続
=========

WebRTC ではさまざまなプロトコルが相互作用してピアー間の接続を確立し、データやメディアの転送を行いますが、この記事ではその仕組みを解説します。

**メモ:** このページは、構造的な完全性と内容の完全性のために、大幅な書き換えが必要です。多くの情報があるのは良いことですが、ここは現在ゴミ捨て場のようなものなので、構成はめちゃくちゃです。

シグナリング
------

残念なことに、WebRTC は中間に何らかのサーバーがなければ接続を作成できません。このサーバーを**シグナルチャンネル**、または**シグナリングサービス**と呼びます。接続を確立する前に情報を交換する伝達手段はどんなものでも構いません。Eメール、はがき、伝書鳩でも...決めるのはあなたです。

交換する必要のある情報はオファーとアンサーと呼ばれ、その中身は下記で説明する SDP (en-US) です。

ピアー A が接続を初期化する側とすると、ピアー A がオファーを作成します。それから選択されたシグナルチャンネルを使ってピアー B にオファーを送ります。ピアー B はシグナルチャンネルからオファーを受け取ると、アンサーを作成します。それからピアー B はピアー A にシグナルチャンネルを使ってアンサーを送り返します。

### セッションディスクリプション

WebRTC 接続のエンドポイント設定は**セッションディスクリプション**と呼ばれます。そこに含まれる情報は、送られるメディアの種類、形式、使用される転送プロトコル、エンドポイントの IP アドレスとポート、またその他メディア転送エンドポイントを記述するのに必要な情報です。この情報を **セッションディスクリプションプロトコル** (SDP (en-US)) を使って交換し、保存します。 SDP データ形式の詳細は RFC 2327 にあります。

ユーザーが WebRTC コールを他のユーザーに開始するとき、**オファー**と呼ばれる特別な記述を作成します。コールする側がコールに必要な設定を提案し、そのすべての情報をオファーの記述に盛り込みます。受け取る側は**アンサー**を返します。アンサーは受け取る側が用意する記述です。このようにして、両デバイスがお互いにメディアデータの交換に必要な情報を共有します。この交換は Interactive Connectivity Establishment (ICE) を使って行われます。ICE とは二つのデバイスが Network Address Translation (NAT) によって隔てられていてもオファーとアンサーを交換するために媒介を利用できるようにするプロトコルです。

各ピアーは 2 つの記述を手に入れます。 **local description** が自分側の記述で、 **remote description** が相手側の記述です。

オファー／アンサーの交換はコールを最初に確立する際に実行されますが、それだけでなくフォーマットや他の設定に変更が必要なときにも随時実行されます。コールの新規作成時でも既存の設定変更時でも、いずれにしてもオファーとアンサーを交換するために以下のような基本的なステップが実行されます。なお、ここでは ICE レイヤーは除外しています。

1. 呼び出す側が `navigator.mediaDevices.getUserMedia()` (en-US) を通じてローカルメディアを取得する
2. 呼び出す側が `RTCPeerConnection` を作成し、`RTCPeerConnection.addTrack()` (en-US) を実行する。(`addStream` が非推奨であるため)
3. 呼び出す側がオファーを作成するために `RTCPeerConnection.createOffer()` (en-US) を実行する
4. 呼び出す側がオファーを *local description* (ローカル側の接続の記述) として設定するために `RTCPeerConnection.setLocalDescription()` (en-US) を実行する
5. 呼び出す側は setLocalDescription() を実行した後、STUN サーバーに問い合わせて ICE 候補を生成する
6. 呼び出す側がシグナリングサーバーを使ってオファーを届けたい相手に送る
7. 受け取る側がオファーを受け取り、それを *remote description* (相手側の接続の記述) として記録するために `RTCPeerConnection.setRemoteDescription()` (en-US) を実行する
8. 受け取る側がコールに必要なセットアップを行う。ローカルメディアを取得し、 `RTCPeerConnection.addTrack()` (en-US) を通じてメディアトラックをピアー接続にアタッチする
9. 受け取る側が `RTCPeerConnection.createAnswer()` (en-US) を実行することでアンサーを作成する
10. 受け取る側が `RTCPeerConnection.setLocalDescription()` (en-US) に作成したアンサーを渡して実行し、アンサーを自身の local description としてセットする。この時点で受け取る側は両側の接続設定を知ることになる。
11. 受け取る側がシグナリングサーバーを使ってアンサーを呼び出す側に送る
12. 呼び出す側がアンサーを受け取る。
13. 呼び出す側がアンサーを remote description として設定するために `RTCPeerConnection.setRemoteDescription()` (en-US) を実行する。これで呼び出す側も両者の設定を知ることになる。設定した通りにメディアが流れ始める。
### Pending and current descriptions

Taking one step deeper into the process, we find that `localDescription` and `remoteDescription`, the properties which return these two descriptions, aren't as simple as they look. Because during renegotiation, an offer might be rejected because it proposes an incompatible format, it's necessary that each endpoint have the ability to propose a new format but not actually switch to it until it's accepted by the other peer. For that reason, WebRTC uses *pending* and *current* descriptions.

The **current description** (which is returned by the `RTCPeerConnection.currentLocalDescription` (en-US) and `RTCPeerConnection.currentRemoteDescription` (en-US) properties) represents the description currently in actual use by the connection. This is the most recent connection that both sides have fully agreed to use.

The **pending description** (returned by `RTCPeerConnection.pendingLocalDescription` (en-US) and `RTCPeerConnection.pendingRemoteDescription` (en-US)) indicates a description which is currently under consideration following a call to `setLocalDescription()` or `setRemoteDescription()`, respectively.

When reading the description (returned by `RTCPeerConnection.localDescription` and `RTCPeerConnection.remoteDescription` (en-US)), the returned value is the value of `pendingLocalDescription`/`pendingRemoteDescription` if there's a pending description (that is, the pending description isn't `null`); otherwise, the current description (`currentLocalDescription`/`currentRemoteDescription`) is returned.

When changing the description by calling `setLocalDescription()` or `setRemoteDescription()`, the specified description is set as the pending description, and the WebRTC layer begins to evaluate whether or not it's acceptable. Once the proposed description has been agreed upon, the value of `currentLocalDescription` or `currentRemoteDescription` is changed to the pending description, and the pending description is set to null again, indicating that there isn't a pending description.

**メモ:** The `pendingLocalDescription` contains not just the offer or answer under consideration, but any local ICE candidates which have already been gathered since the offer or answer was created. Similarly, `pendingRemoteDescription` includes any remote ICE candidates which have been provided by calls to `RTCPeerConnection.addIceCandidate()` (en-US).

See the individual articles on these properties and methods for more specifics, and Codecs used by WebRTC (en-US) for information about codecs supported by WebRTC and which are compatible with which browsers. The codecs guide also offers guidance to help you choose the best codecs for your needs.

ICE candidates
--------------

As well as exchanging information about the media (discussed above in Offer/Answer and SDP), peers must exchange information about the network connection. This is known as an **ICE candidate** and details the available methods the peer is able to communicate (directly or through a TURN server). Typically, each peer will propose its best candidates first, making their way down the line toward their worse candidates. Ideally, candidates are UDP (since it's faster, and media streams are able to recover from interruptions relatively easily), but the ICE standard does allow TCP candidates as well.

**メモ:** Generally, ICE candidates using TCP are only going to be used when UDP is not available or is restricted in ways that make it not suitable for media streaming. Not all browsers support ICE over TCP, however.

ICE allows candidates to represent connections over either TCP or UDP (en-US), with UDP generally being preferred (and being more widely supported). Each protocol supports a few types of candidate, with the candidate types defining how the data makes its way from peer to peer.

### UDP candidate types

UDP candidates (candidates with their `protocol` (en-US) set to `udp`) can be one of these types:

`host`

A host candidate is one for which its `ip` (en-US) address is the actual, direct IP address of the remote peer.

`prflx`

A peer reflexive candidate is one whose IP address comes from a symmetric NAT between the two peers, usually as an additional candidate during trickle ICE (that is, additional candidate exchanges that occur after primary signaling but before the connection verification phase is finished).

`srflx`

A server reflexive candidate is generated by a STUN/TURN server; the connection's initiator requests a candidate from the STUN server, which forwards the request through the remote peer's NAT, which creates and returns a candidate whose IP address is local to the remote peer. The STUN server then replies to the initiator's request with a candidate whose IP address is unrelated to the remote peer.

`relay`

A relay candidate is generated just like a server reflexive candidate (`"srflx"`), but using TURN instead of STUN.

### TCP candidate types

TCP candidates (that is, candidates whose `protocol` (en-US) is `tcp`) can be of these types:

`active`

The transport will try to open an outbound connection but won't receive incoming connection requests. This is the most common type, and the only one that most user agents will gather.

`passive`

The transport will receive incoming connection attempts but won't attempt a connection itself.

`so`

The transport will try to simultaneously open a connection with its peer.

### Choosing a candidate pair

The ICE layer selects one of the two peers to serve as the **controlling agent**. This is the ICE agent which will make the final decision as to which candidate pair to use for the connection. The other peer is called the **controlled agent**. You can identify which one your end of the connection is by examining the value of `RTCIceCandidate.transport.role` (en-US), although in general it doesn't matter which is which.

The controlling agent not only takes responsibility for making the final decision as to which candidate pair to use, but also for signaling that selection to the controlled agent by using STUN and an updated offer, if necessary. The controlled agent just waits to be told which candidate pair to use.

It's important to keep in mind that a single ICE session may result in the controlling agent choosing more than one candidate pair. Each time it does so and shares that information with the controlled agent, the two peers reconfigure their connection to use the new configuration described by the new candidate pair.

Once the ICE session is complete, the configuration that's currently in effect is the final one, unless an ICE reset occurs.

At the end of each generation of candidates, an end-of-candidates notification is sent in the form of an `RTCIceCandidate` (en-US) whose `candidate` (en-US) property is an empty string. This candidate should still be added to the connection using `addIceCandidate()` (en-US) method, as usual, in order to deliver that notification to the remote peer.

When there are no more candidates at all to be expected during the current negotiation exchange, an end-of-candidates notification is sent by delivering a `RTCIceCandidate` (en-US) whose `candidate` (en-US) property is `null`. This message does *not* need to be sent to the remote peer. It's a legacy notification of a state which can be detected instead by watching for the `iceGatheringState` (en-US) to change to `complete`, by watching for the `icegatheringstatechange` (en-US) event.

When things go wrong
--------------------

During negotiation, there will be times when things just don't work out. For example, when renegotiating a connection—for example, to adapt to changing hardware or network configurations—it's possible that negotiation could reach a dead end, or some form of error might occur that prevents negotiation at all. There may be permissions issues or other problems as well, for that matter.

### ICE rollbacks

When renegotiating a connection that's already active and a situation arises in which the negotiation fails, you don't really want to kill the already-running call. After all, you were most likely just trying to upgrade or downgrade the connection, or to otherwise make adaptations to an ongoing session. Aborting the call would be an excessive reaction in that situation.

Instead, you can initiate an **ICE rollback**. A rollback restores the SDP offer (and the connection configuration by extension) to the configuration it had the last time the connection's `signalingState` (en-US) was `stable`.

To programmatically initiate a rollback, send a description whose `type` (en-US) is `rollback`. Any other properties in the description object are ignored.

In addition, the ICE agent will automatically initiate a rollback when a peer that had previously created an offer receives an offer from the remote peer. In other words, if the local peer is in the state `have-local-offer`, indicating that the local peer had previously *sent* an offer, calling `setRemoteDescription()` with a *received* offer triggers rollback so that the negotiation switches from the remote peer being the caller to the local peer being the caller.

### ICE restarts

For now, see ICE restart (en-US).

The entire exchange in a complicated diagram
--------------------------------------------

![A complete architectural diagram showing the whole WebRTC process.](/ja/docs/Web/API/WebRTC_API/Connectivity/webrtc-complete-diagram.png)


WebRTC プロトコル入門 - Web API

WebRTC プロトコル入門
==============

この記事では、 WebRTC API の基礎となっているプロトコルについて説明します。

ICE
---

Interactive Connectivity Establishment (ICE) は、ウェブブラウザーをピアーと接続することを可能にするフレームワークです。さまざまな理由から、ピアー A からピアー B に直接接続することはできません。ファイアウォールをバイパスする必要があるからです。ファイアウォールは直接接続を開くことを妨害したり、端末がパブリック IP アドレスを持たない多くの場合にはユニークなアドレスを与えたり、ルーターがピアーとの直接接続を許さない場合にはサーバー経由でデータをリレーしたりします。以下で説明するように、 ICE は STUN や TURN サーバーを使用してこれを解決しています。

STUN
----

Session Traversal Utilities for NAT (STUN) は、パブリックアドレスを発見し、ピアーとの直接接続を妨害するルーターの制限を特定するためのプロトコルです。

クライアントがインターネット上の STUN サーバーにリクエストを送信すると、サーバーは、クライアントのパブリックアドレスと、ルーターの NAT 内部にアクセス可能かどうかを答えます。

![An interaction between two users of a WebRTC application involving a STUN server.](/ja/docs/Web/API/WebRTC_API/Protocols/webrtc-stun.png)

NAT
---

ネットワークアドレス変換 (Network Address Translation; NAT) は、端末にパブリック IP アドレスを割り当てるために使われます。ルーターはパブリック IP アドレスを持ち、ルーターに接続されたすべての端末はプライベート IP アドレスを持ちます。リクエストが送られると、端末のプライベート IP から、特定のポートを持つルーターのパブリック IP へ変換されます。こうすることで、各端末にユニークな IP アドレスを割り当てずともインターネット上で発見することができるようになります。

ルーターによっては、ネットワーク上の端末に接続できる相手に制限をかけている場合があります。つまり、 STUN サーバーが発見できるパブリック IP アドレスを持っていたとしても、すべての相手が接続を張れるわけではないということです。このような状況では、 TURN を使う必要があります。

TURN
----

NAT を使用するルーターによっては、 'Symmetric NAT' と呼ばれる制限をかけています。その場合、ルーターは過去に接続したことのあるピアーから来る接続しか受け入れることができません。

Traversal Using Relays around NAT (TURN) は、 TURN サーバーとの接続を開き、そのサーバーを介してすべての情報を中継することで、 Symmetric NAT の制限を回避することを意図しています。 TURN サーバーとの接続を作成し、すべてのピアにサーバーにパケットを送信するように指示し、そのパケットはあなたに転送されます。これは明らかにオーバーヘッドを伴うので、他に方法がない場合にのみ使用します。

![An interaction between two users of a WebRTC application involving STUN and TURN servers.](/ja/docs/Web/API/WebRTC_API/Protocols/webrtc-turn.png)

SDP
---

Session Description Protocol (SDP) とは、解像度、フォーマット、コーデック、暗号化などのマルチメディアコンテンツを指定するための標準です。これにより、データが転送された際に双方が理解できるようになります。本来、これらはメディアコンテンツそのものではなくそのコンテンツを指定するメタデータです。

技術的には、 SDP は真のプロトコルではなく、端末間でメディアを共有する接続を記述するために使用されるデータ形式です。

SDP の文書化は、このドキュメントの範囲外です。ただし、ここで注目すべき点がいくつかあります。

### 構造

SDP は、 1 行以上の UTF-8 テキストで構成され、それぞれ 1 文字の型で始まり、等号 (`"="`) が続き、型に依存する形式で値または説明からなる構造化テキストが続きます。ある文字で始まるテキストの行は、一般に "*letter*-lines" と呼ばれています。例えば、メディアの説明を提供する行は `"m"` という型なので、それらの行は「m 行」と呼ばれます。

### 詳細情報

SDP についてより詳しく知りたい方は、以下の有用な資料をご覧ください。

* 仕様書: RFC 4566: SDP: Session Description Protocol
* IANA registry of SDP parameters


PeerJS によるインターネット接続電話の構築 - Web API

PeerJS によるインターネット接続電話の構築
========================

* 次のページ  (en-US)

WebRTC の主な課題の 1 つが、使用したり開発したりするのがかなり複雑だということです。シグナリングサービスを処理したり、正しいエンドポイントを呼び出すタイミングを把握したりすると、混乱してしまいます。しかし、良いニュースもあります。 PeerJS は WebRTC のフレームワークで、アプリケーションの機能に集中できるように、通信とシグナリングのロジックをすべて抽象化します。 PeerJS にはクライアント側のフレームワークとサーバーの 2 つの部分があります。

この一連の記事では、 PeerJS を使用して単純な電話アプリケーションを作成します。サーバーサイドフレームワークとクライアントサイドフレームワークの両方を使用しますが、ほとんどの作業はクライアントサイドのコードを扱うことになります。

### 前提条件

このチュートリアルは中級レベルです。このチュートリアルに挑戦する前に、次のものに親しんでいる必要があります。

* バニラ JavaScript
* Node
* Express
* HTML

始める前に、 node と Yarn がインストールされていることを確認してください（後の記事の説明では Yarn を想定していますが、推奨するなら npm や他のマネージャを使用するのも自由です）。

**メモ:** 手順を追うほうが学習しやすいという方には、このコードによるチュートリアルも提供していますので、代わりに使用してください。

### 目次

1. セットアップ (en-US)
2. ピアの接続 (en-US)
    1. マイクの使用権限を取得 (en-US)
    2. HTML の表示と隠蔽 (en-US)
    3. ピアコネクションの作成 (en-US)
    4. 呼び出しの作成 (en-US)
    5. 呼び出しへの応答 (en-US)
    6. 通話の終了 (en-US)
3. 配布と追加の読み物 (en-US)
* 次のページ  (en-US)


シグナリングとビデオ通話 - Web API

シグナリングとビデオ通話
============

WebRTC は、デバイス間のリアルタイムな P2P(ピア・ツー・ピア) 接続を通した情報交換を可能にします。接続は **シグナリング** と呼ばれる、ピアの発見とピアとの交渉のプロセスを通じて確立されます。このチュートリアルでは、双方向のビデオ通話を実装していきます。

WebRTC は制約のある状況下で、音声、動画、データをリアルタイムでやり取りするための完全なピア・ツー・ピアな技術です。ピア同士の発見と交渉のプロセスは、他の記事でも議論されているように (en-US)、お互いに異なるネットワーク上にいるデバイス同士で行われることになります。この **シグナリング** と呼ばれるプロセスは、デバイス同士がお互いに合意済みの第三者のサーバへの接続を含みます。この第三者サーバを通してデバイスはお互いの位置を確認し、交渉のためのメッセージをやり取りすることが出来ます。

このドキュメントでは、私達の WebSocket のドキュメント(この記事へのリンクは追加予定で、まだ存在しません。)の中で作られたWebSocket チャット を、ユーザ間の双方向ビデオ通話をサポートするように改良していきます。もしコードを実際に動かしてみたい場合は、Glitch example や、remix the example を試すことが出来ます。また Github でプロジェクト全体も公開されています。

>
> **注意:** Glitch の例を試す場合、コードの小さな更新でも接続がリセットされることになります。加えて、Glitch インスタンスは手軽な試行とテストのためにあるので、タイムアウト期間が短く設定されています。
>
>
>

シグナリングサーバ
---------

インターネット越しに二つのデバイス間で WebRTC 接続を確立するためには **シグナリングサーバ** が必要になります。シグナリングサーバの仕事は、出来得る限り最小のプライベートな情報の露出で、ピア同士がお互いを発見し接続するよう仲介者となることです。どうやってこのサーバを作れるのでしょうか、また、シグナリングのプロセスはどのように行われるのでしょうか？

まずシグナリングサーバ自体が必要です。 WebRTC はシグナリング情報に特定の伝送プロトコルを指定していません。 WebSocket や `XMLHttpRequest` から伝書鳩だって構いません。好きなものを使用して二つのピア間でシグナリング情報を交換できます。

サーバはシグナリング情報の中身を理解したり解釈したりする必要はない、と把握しておくことが重要です。 SDP (en-US) ですが、これもそれほど大事な情報ではありません。シグナリングサーバを通過するメッセージの内容は、事実上、ブラックボックスです。重要なのは、 ICE サブシステムであるピアに対して、もう一方のピアにシグナリング情報を送信するよう指示する場合です。もしピアがシグナリング情報を送信すると、他方のピアはその情報を受信して独自の ICE サブシステムへと渡す方法を知ることが出来ます。 シグナリングサーバの役割は、こうした情報を仲介することだけです。情報の中身は内容はサーバにとってまったく関係ありません。

### Readying the chat server for signaling

Our chat server uses the WebSocket API to send information as JSON strings between each client and the server. The server supports several message types to handle tasks, such as registering new users, setting usernames, and sending public chat messages.

To allow the server to support signaling and ICE negotiation, we need to update the code. We'll have to allow directing messages to one specific user instead of broadcasting to all connected users, and ensure unrecognized message types are passed through and delivered, without the server needing to know what they are. This lets us send signaling messages using this same server, instead of needing a separate server.

Let's take a look at changes we need to make to the chat server to support WebRTC signaling. This is in the file `chatserver.js`.

First up is the addition of the function `sendToOneUser()`. As the name suggests, this sends a stringified JSON message to a particular username.

```js
function sendToOneUser(target, msgString) {
  connectionArray.find((conn) => conn.username === target).send(msgString);
}
```

This function iterates over the list of connected users until it finds one matching the specified username, then sends the message to that user. The parameter `msgString` is a stringified JSON object. We could have made it receive our original message object, but in this example it's more efficient this way. Since the message has already been stringified, we can send it with no further processing. Each entry in `connectionArray` is a `WebSocket` object, so we can just call its `send()` method directly.

Our original chat demo didn't support sending messages to a specific user. The next task is to update the main WebSocket message handler to support doing so. This involves a change near the end of the `"connection"` message handler:

```js
if (sendToClients) {
  const msgString = JSON.stringify(msg);

  if (msg.target && msg.target.length !== 0) {
    sendToOneUser(msg.target, msgString);
  } else {
    for (const connection of connectionArray) {
      connection.send(msgString);
    }
  }
}
```

This code now looks at the pending message to see if it has a `target` property. If that property is present, it specifies the username of the client to which the message is to be sent, and we call `sendToOneUser()` to send the message to them. Otherwise, the message is broadcast to all users by iterating over the connection list, sending the message to each user.

As the existing code allows the sending of arbitrary message types, no additional changes are required. Our clients can now send messages of unknown types to any specific user, letting them send signaling messages back and forth as desired.

That's all we need to change on the server side of the equation. Now let's consider the signaling protocol we will implement.

### Designing the signaling protocol

Now that we've built a mechanism for exchanging messages, we need a protocol defining how those messages will look. This can be done in a number of ways; what's demonstrated here is just one possible way to structure signaling messages.

This example's server uses stringified JSON objects to communicate with its clients. This means our signaling messages will be in JSON format, with contents which specify what kind of messages they are as well as any additional information needed in order to handle the messages properly.

#### Exchanging session descriptions

When starting the signaling process, an **offer** is created by the user initiating the call. This offer includes a session description, in SDP (en-US) format, and needs to be delivered to the receiving user, which we'll call the **callee**. The callee responds to the offer with an **answer** message, also containing an SDP description. Our signaling server will use WebSocket to transmit offer messages with the type `"video-offer"`, and answer messages with the type `"video-answer"`. These messages have the following fields:

`type`

The message type; either `"video-offer"` or `"video-answer"`.

`name`

The sender's username.

`target`

The username of the person to receive the description (if the caller is sending the message, this specifies the callee, and vice versa).

`sdp`

The SDP (Session Description Protocol) string describing the local end of the connection from the perspective of the sender (or the remote end of the connection from the receiver's point of view).

At this point, the two participants know which codecs (en-US) and codec parameters (en-US) are to be used for this call. They still don't know how to transmit the media data itself though. This is where Interactive Connectivity Establishment (ICE) comes in.

### Exchanging ICE candidates

Two peers need to exchange ICE candidates to negotiate the actual connection between them. Every ICE candidate describes a method that the sending peer is able to use to communicate. Each peer sends candidates in the order they're discovered, and keeps sending candidates until it runs out of suggestions, even if media has already started streaming.

An `icecandidate` (en-US) event is sent to the `RTCPeerConnection` to complete the process of adding a local description using `pc.setLocalDescription(offer)`.

Once the two peers agree upon a mutually-compatible candidate, that candidate's SDP is used by each peer to construct and open a connection, through which media then begins to flow. If they later agree on a better (usually higher-performance) candidate, the stream may change formats as needed.

Though not currently supported, a candidate received after media is already flowing could theoretically also be used to downgrade to a lower-bandwidth connection if needed.

Each ICE candidate is sent to the other peer by sending a JSON message of type `"new-ice-candidate"` over the signaling server to the remote peer. Each candidate message include these fields:

`type`

The message type: `"new-ice-candidate"`.

`target`

The username of the person with whom negotiation is underway; the server will direct the message to this user only.

`candidate`

The SDP candidate string, describing the proposed connection method. You typically don't need to look at the contents of this string. All your code needs to do is route it through to the remote peer using the signaling server.

Each ICE message suggests a communication protocol (TCP or UDP), IP address, port number, connection type (for example, whether the specified IP is the peer itself or a relay server), along with other information needed to link the two computers together. This includes NAT or other networking complexity.

>
> **Note:** The important thing to note is this: the only thing your code is responsible for during ICE negotiation is accepting outgoing candidates from the ICE layer and sending them across the signaling connection to the other peer when your `onicecandidate` (en-US) handler is executed, and receiving ICE candidate messages from the signaling server (when the `"new-ice-candidate"` message is received) and delivering them to your ICE layer by calling `RTCPeerConnection.addIceCandidate()` (en-US). That's it.
>
>
> The contents of the SDP are irrelevant to you in essentially all cases. Avoid the temptation to try to make it more complicated than that until you really know what you're doing. That way lies madness.
>
>
>

All your signaling server now needs to do is send the messages it's asked to. Your workflow may also demand login/authentication functionality, but such details will vary.

>
> **Note:** The `onicecandidate` (en-US) Event and `createAnswer()` (en-US) Promise are both async calls which are handled separately. Be sure that your signaling does not change order! For example `addIceCandidate()` (en-US) with the server's ice candidates must be called after setting the answer with `setRemoteDescription()` (en-US).
>
>
>

### Signaling transaction flow

The signaling process involves this exchange of messages between two peers using an intermediary, the signaling server. The exact process will vary, of course, but in general there are a few key points at which signaling messages get handled:

The signaling process involves this exchange of messages among a number of points:

* Each user's client running within a web browser
* Each user's web browser
* The signaling server
* The web server hosting the chat service

Imagine that Naomi and Priya are engaged in a discussion using the chat software, and Naomi decides to open a video call between the two. Here's the expected sequence of events:

![Diagram of the signaling process](/ja/docs/Web/API/WebRTC_API/Signaling_and_video_calling/webrtc_-_signaling_diagram.svg)

We'll see this detailed more over the course of this article.

### ICE candidate exchange process

When each peer's ICE layer begins to send candidates, it enters into an exchange among the various points in the chain that looks like this:

![Diagram of ICE candidate exchange process](/ja/docs/Web/API/WebRTC_API/Signaling_and_video_calling/webrtc_-_ice_candidate_exchange.svg)

Each side sends candidates to the other as it receives them from their local ICE layer; there is no taking turns or batching of candidates. As soon as the two peers agree upon one candidate that they can both use to exchange the media, media begins to flow. Each peer continues to send candidates until it runs out of options, even after the media has already begun to flow. This is done in hopes of identifying even better options than the one initially selected.

If conditions change (for example, the network connection deteriorates), one or both peers might suggest switching to a lower-bandwidth media resolution, or to an alternative codec. That triggers a new exchange of candidates, after which another media format and/or codec change may take place. In the guide Codecs used by WebRTC (en-US) you can learn more about the codecs which WebRTC requires browsers to support, which additional codecs are supported by which browsers, and how to choose the best codecs to use.

Optionally, see RFC 8445: Interactive Connectivity Establishment, section 2.3 ("Negotiating Candidate Pairs and Concluding ICE") if you want greater understanding of how this process is completed inside the ICE layer. You should note that candidates are exchanged and media starts to flow as soon as the ICE layer is satisfied. This is all taken care of behind the scenes. Our role is to send the candidates, back and forth, through the signaling server.

The client application
----------------------

The core to any signaling process is its message handling. It's not necessary to use WebSockets for signaling, but it is a common solution. You should, of course, select a mechanism for exchanging signaling information that is appropriate for your application.

Let's update the chat client to support video calling.

### Updating the HTML

The HTML for our client needs a location for video to be presented. This requires video elements, and a button to hang up the call:

```html
<div class="flexChild" id="camera-container">
  <div class="camera-box">
    <video id="received\_video" autoplay></video>
    <video id="local\_video" autoplay muted></video>
    <button id="hangup-button" onclick="hangUpCall();" disabled>Hang Up</button>
  </div>
</div>
```

The page structure defined here is using `<div>` elements, giving us full control over the page layout by enabling the use of CSS. We'll skip layout detail in this guide, but take a look at the CSS on GitHub to see how we handled it. Take note of the two `<video>` elements, one for your self-view, one for the connection, and the `<button>` element.

The `<video>` element with the `id` "`received_video`" will present video received from the connected user. We specify the `autoplay` attribute, ensuring once the video starts arriving, it immediately plays. This removes any need to explicitly handle playback in our code. The "`local_video`" `<video>` element presents a preview of the user's camera; specifying the `muted` attribute, as we don't need to hear local audio in this preview panel.

Finally, the "`hangup-button`" `<button>`, to disconnect from a call, is defined and configured to start disabled (setting this as our default for when no call is connected) and apply the function `hangUpCall()` on click. This function's role is to close the call, and send a signalling server notification to the other peer, requesting it also close.

### The JavaScript code

We'll divide this code into functional areas to more easily describe how it works. The main body of this code is found in the `connect()` function: it opens up a `WebSocket` server on port 6503, and establishes a handler to receive messages in JSON object format. This code generally handles text chat messages as it did previously.

#### Sending messages to the signaling server

Throughout our code, we call `sendToServer()` in order to send messages to the signaling server. This function uses the WebSocket connection to do its work:

```js
function sendToServer(msg) {
  const msgJSON = JSON.stringify(msg);

  connection.send(msgJSON);
}
```

The message object passed into this function is converted into a JSON string by calling `JSON.stringify()`, then we call the WebSocket connection's `send()` function to transmit the message to the server.

#### UI to start a call

The code which handles the `"userlist"` message calls `handleUserlistMsg()`. Here we set up the handler for each connected user in the user list displayed to the left of the chat panel. This function receives a message object whose `users` property is an array of strings specifying the user names of every connected user.

```js
function handleUserlistMsg(msg) {
  const listElem = document.querySelector(".userlistbox");

  while (listElem.firstChild) {
    listElem.removeChild(listElem.firstChild);
  }

  msg.users.forEach((username) => {
    const item = document.createElement("li");
    item.appendChild(document.createTextNode(username));
    item.addEventListener("click", invite, false);

    listElem.appendChild(item);
  });
}
```

After getting a reference to the `<ul>` which contains the list of user names into the variable `listElem`, we empty the list by removing each of its child elements.

>
> **Note:** Obviously, it would be more efficient to update the list by adding and removing individual users instead of rebuilding the whole list every time it changes, but this is good enough for the purposes of this example.
>
>
>

Then we iterate over the array of user names using `forEach()`. For each name, we create a new `<li>` element, then create a new text node containing the user name using `createTextNode()`. That text node is added as a child of the `<li>` element. Next, we set a handler for the `click` event on the list item, that clicking on a user name calls our `invite()` method, which we'll look at in the next section.

Finally, we append the new item to the `<ul>` that contains all of the user names.

#### Starting a call

When the user clicks on a username they want to call, the `invite()` function is invoked as the event handler for that `click` event:

```js
const mediaConstraints = {
  audio: true, // We want an audio track
  video: true, // And we want a video track
};

function invite(evt) {
  if (myPeerConnection) {
    alert("You can't start a call because you already have one open!");
  } else {
    const clickedUsername = evt.target.textContent;

    if (clickedUsername === myUsername) {
      alert(
        "I'm afraid I can't let you talk to yourself. That would be weird.",
      );
      return;
    }

    targetUsername = clickedUsername;
    createPeerConnection();

    navigator.mediaDevices
      .getUserMedia(mediaConstraints)
      .then((localStream) => {
        document.getElementById("local\_video").srcObject = localStream;
        localStream
          .getTracks()
          .forEach((track) => myPeerConnection.addTrack(track, localStream));
      })
      .catch(handleGetUserMediaError);
  }
}
```

This begins with a basic sanity check: is the user already connected? If there's already a `RTCPeerConnection`, they obviously can't make a call. Then the name of the user that was clicked upon is obtained from the event target's `textContent` property, and we check to be sure that it's not the same user that's trying to start the call.

Then we copy the name of the user we're calling into the variable `targetUsername` and call `createPeerConnection()`, a function which will create and do basic configuration of the `RTCPeerConnection`.

Once the `RTCPeerConnection` has been created, we request access to the user's camera and microphone by calling `MediaDevices.getUserMedia()`, which is exposed to us through the `MediaDevices.getUserMedia` property. When this succeeds, fulfilling the returned promise, our `then` handler is executed. It receives, as input, a `MediaStream` object representing the stream with audio from the user's microphone and video from their webcam.

>
> **Note:** We could restrict the set of permitted media inputs to a specific device or set of devices by calling `navigator.mediaDevices.enumerateDevices()` to get a list of devices, filtering the resulting list based on our desired criteria, then using the selected devices' `deviceId` (en-US) values in the `deviceId` field of the `mediaConstraints` object passed into `getUserMedia()`. In practice, this is rarely if ever necessary, since most of that work is done for you by `getUserMedia()`.
>
>
>

We attach the incoming stream to the local preview `<video>` element by setting the element's `srcObject` property. Since the element is configured to automatically play incoming video, the stream begins playing in our local preview box.

We then iterate over the tracks in the stream, calling `addTrack()` (en-US) to add each track to the `RTCPeerConnection`. Even though the connection is not fully established yet, you can begin sending data when you feel it's appropriate to do so. Media received before the ICE negotiation is completed may be used to help ICE decide upon the best connectivity approach to take, thus aiding in the negotiation process.

Note that for native apps, such as a phone application, you should not begin sending until the connection has been accepted at both ends, at a minimum, to avoid inadvertently sending video and/or audio data when the user isn't prepared for it.

As soon as media is attached to the `RTCPeerConnection`, a `negotiationneeded` (en-US) event is triggered at the connection, so that ICE negotiation can be started.

If an error occurs while trying to get the local media stream, our catch clause calls `handleGetUserMediaError()`, which displays an appropriate error to the user as required.

#### Handling getUserMedia() errors

If the promise returned by `getUserMedia()` concludes in a failure, our `handleGetUserMediaError()` function performs.

```js
function handleGetUserMediaError(e) {
  switch (e.name) {
    case "NotFoundError":
      alert(
        "Unable to open your call because no camera and/or microphone" +
          "were found.",
      );
      break;
    case "SecurityError":
    case "PermissionDeniedError":
      // Do nothing; this is the same as the user canceling the call.
      break;
    default:
      alert(`Error opening your camera and/or microphone: ${e.message}`);
      break;
  }

  closeVideoCall();
}
```

An error message is displayed in all cases but one. In this example, we ignore `"SecurityError"` and `"PermissionDeniedError"` results, treating refusal to grant permission to use the media hardware the same as the user canceling the call.

Regardless of why an attempt to get the stream fails, we call our `closeVideoCall()` function to shut down the `RTCPeerConnection`, and release any resources already allocated by the process of attempting the call. This code is designed to safely handle partially-started calls.

#### Creating the peer connection

The `createPeerConnection()` function is used by both the caller and the callee to construct their `RTCPeerConnection` objects, their respective ends of the WebRTC connection. It's invoked by `invite()` when the caller tries to start a call, and by `handleVideoOfferMsg()` when the callee receives an offer message from the caller.

```js
function createPeerConnection() {
  myPeerConnection = new RTCPeerConnection({
    iceServers: [
      // Information about ICE servers - Use your own!
      {
        urls: "stun:stun.stunprotocol.org",
      },
    ],
  });

  myPeerConnection.onicecandidate = handleICECandidateEvent;
  myPeerConnection.ontrack = handleTrackEvent;
  myPeerConnection.onnegotiationneeded = handleNegotiationNeededEvent;
  myPeerConnection.onremovetrack = handleRemoveTrackEvent;
  myPeerConnection.oniceconnectionstatechange =
    handleICEConnectionStateChangeEvent;
  myPeerConnection.onicegatheringstatechange =
    handleICEGatheringStateChangeEvent;
  myPeerConnection.onsignalingstatechange = handleSignalingStateChangeEvent;
}
```

When using the `RTCPeerConnection()` constructor, we will specify an object providing configuration parameters for the connection. We use only one of these in this example: `iceServers`. This is an array of objects describing STUN and/or TURN servers for the ICE layer to use when attempting to establish a route between the caller and the callee. These servers are used to determine the best route and protocols to use when communicating between the peers, even if they're behind a firewall or using NAT.

>
> **Note:** You should always use STUN/TURN servers which you own, or which you have specific authorization to use. This example is using a known public STUN server but abusing these is bad form.
>
>
>

Each object in `iceServers` contains at least a `urls` field providing URLs at which the specified server can be reached. It may also provide `username` and `credential` values to allow authentication to take place, if needed.

After creating the `RTCPeerConnection`, we set up handlers for the events that matter to us.

The first three of these event handlers are required; you have to handle them to do anything involving streamed media with WebRTC. The rest aren't strictly required but can be useful, and we'll explore them. There are a few other events available that we're not using in this example, as well. Here's a summary of each of the event handlers we will be implementing:

`onicecandidate` (en-US)

The local ICE layer calls your `icecandidate` (en-US) event handler, when it needs you to transmit an ICE candidate to the other peer, through your signaling server. See Sending ICE candidates for more information and to see the code for this example.

`ontrack` (en-US)

This handler for the `track` (en-US) event is called by the local WebRTC layer when a track is added to the connection. This lets you connect the incoming media to an element to display it, for example. See Receiving new streams for details.

`onnegotiationneeded` (en-US)

This function is called whenever the WebRTC infrastructure needs you to start the session negotiation process anew. Its job is to create and send an offer, to the callee, asking it to connect with us. See Starting negotiation to see how we handle this.

`onremovetrack`

This counterpart to `ontrack` is called to handle the `removetrack` event; it's sent to the `RTCPeerConnection` when the remote peer removes a track from the media being sent. See Handling the removal of tracks.

`oniceconnectionstatechange` (en-US)

The `iceconnectionstatechange` (en-US) event is sent by the ICE layer to let you know about changes to the state of the ICE connection. This can help you know when the connection has failed, or been lost. We'll look at the code for this example in ICE connection state below.

`onicegatheringstatechange` (en-US)

The ICE layer sends you the `icegatheringstatechange` (en-US) event, when the ICE agent's process of collecting candidates shifts, from one state to another (such as starting to gather candidates or completing negotiation). See ICE gathering state below.

`onsignalingstatechange` (en-US)

The WebRTC infrastructure sends you the `signalingstatechange` (en-US) message when the state of the signaling process changes (or if the connection to the signaling server changes). See Signaling state to see our code.

#### Starting negotiation

Once the caller has created its `RTCPeerConnection`, created a media stream, and added its tracks to the connection as shown in Starting a call, the browser will deliver a `negotiationneeded` (en-US) event to the `RTCPeerConnection` to indicate that it's ready to begin negotiation with the other peer. Here's our code for handling the `negotiationneeded` (en-US) event:

```js
function handleNegotiationNeededEvent() {
  myPeerConnection
    .createOffer()
    .then((offer) => myPeerConnection.setLocalDescription(offer))
    .then(() => {
      sendToServer({
        name: myUsername,
        target: targetUsername,
        type: "video-offer",
        sdp: myPeerConnection.localDescription,
      });
    })
    .catch(reportError);
}
```

To start the negotiation process, we need to create and send an SDP offer to the peer we want to connect to. This offer includes a list of supported configurations for the connection, including information about the media stream we've added to the connection locally (that is, the video we want to send to the other end of the call), and any ICE candidates gathered by the ICE layer already. We create this offer by calling `myPeerConnection.createOffer()` (en-US).

When `createOffer()` succeeds (fulfilling the promise), we pass the created offer information into `myPeerConnection.setLocalDescription()` (en-US), which configures the connection and media configuration state for the caller's end of the connection.

>
> **Note:** Technically speaking, the string returned by `createOffer()` is an RFC 3264 offer.
>
>
>

We know the description is valid, and has been set, when the promise returned by `setLocalDescription()` is fulfilled. This is when we send our offer to the other peer by creating a new `"video-offer"` message containing the local description (now the same as the offer), then sending it through our signaling server to the callee. The offer has the following members:

`type`

The message type: `"video-offer"`.

`name`

The caller's username.

`target`

The name of the user we wish to call.

`sdp`

The SDP string describing the offer.

If an error occurs, either in the initial `createOffer()` or in any of the fulfillment handlers that follow, an error is reported by invoking our `reportError()` function.

Once `setLocalDescription()`'s fulfillment handler has run, the ICE agent begins sending `icecandidate` (en-US) events to the `RTCPeerConnection`, one for each potential configuration it discovers. Our handler for the `icecandidate` event is responsible for transmitting the candidates to the other peer.

#### Session negotiation

Now that we've started negotiation with the other peer and have transmitted an offer, let's look at what happens on the callee's side of the connection for a while. The callee receives the offer and calls `handleVideoOfferMsg()` function to process it. Let's see how the callee handles the `"video-offer"` message.

##### Handling the invitation

When the offer arrives, the callee's `handleVideoOfferMsg()` function is called with the `"video-offer"` message that was received. This function needs to do two things. First, it needs to create its own `RTCPeerConnection` and add the tracks containing the audio and video from its microphone and webcam to that. Second, it needs to process the received offer, constructing and sending its answer.

```js
function handleVideoOfferMsg(msg) {
  let localStream = null;

  targetUsername = msg.name;
  createPeerConnection();

  const desc = new RTCSessionDescription(msg.sdp);

  myPeerConnection
    .setRemoteDescription(desc)
    .then(() => navigator.mediaDevices.getUserMedia(mediaConstraints))
    .then((stream) => {
      localStream = stream;
      document.getElementById("local\_video").srcObject = localStream;

      localStream
        .getTracks()
        .forEach((track) => myPeerConnection.addTrack(track, localStream));
    })
    .then(() => myPeerConnection.createAnswer())
    .then((answer) => myPeerConnection.setLocalDescription(answer))
    .then(() => {
      const msg = {
        name: myUsername,
        target: targetUsername,
        type: "video-answer",
        sdp: myPeerConnection.localDescription,
      };

      sendToServer(msg);
    })
    .catch(handleGetUserMediaError);
}
```

This code is very similar to what we did in the `invite()` function back in Starting a call. It starts by creating and configuring an `RTCPeerConnection` using our `createPeerConnection()` function. Then it takes the SDP offer from the received `"video-offer"` message and uses it to create a new `RTCSessionDescription` object representing the caller's session description.

That session description is then passed into `myPeerConnection.setRemoteDescription()` (en-US). This establishes the received offer as the description of the remote (caller's) end of the connection. If this is successful, the promise fulfillment handler (in the `then()` clause) starts the process of getting access to the callee's camera and microphone using `getUserMedia()`, adding the tracks to the connection, and so forth, as we saw previously in `invite()`.

Once the answer has been created using `myPeerConnection.createAnswer()` (en-US), the description of the local end of the connection is set to the answer's SDP by calling `myPeerConnection.setLocalDescription()` (en-US), then the answer is transmitted through the signaling server to the caller to let them know what the answer is.

Any errors are caught and passed to `handleGetUserMediaError()`, described in Handling getUserMedia() errors.

>
> **Note:** As is the case with the caller, once the `setLocalDescription()` fulfillment handler has run, the browser begins firing `icecandidate` (en-US) events that the callee must handle, one for each candidate that needs to be transmitted to the remote peer.
>
>
>

##### Sending ICE candidates

The ICE negotiation process involves each peer sending candidates to the other, repeatedly, until it runs out of potential ways it can support the `RTCPeerConnection`'s media transport needs. Since ICE doesn't know about your signaling server, your code handles transmission of each candidate in your handler for the `icecandidate` (en-US) event.

Your `onicecandidate` (en-US) handler receives an event whose `candidate` property is the SDP describing the candidate (or is `null` to indicate that the ICE layer has run out of potential configurations to suggest). The contents of `candidate` are what you need to transmit using your signaling server. Here's our example's implementation:

```js
function handleICECandidateEvent(event) {
  if (event.candidate) {
    sendToServer({
      type: "new-ice-candidate",
      target: targetUsername,
      candidate: event.candidate,
    });
  }
}
```

This builds an object containing the candidate, then sends it to the other peer using the `sendToServer()` function previously described in Sending messages to the signaling server. The message's properties are:

`type`

The message type: `"new-ice-candidate"`.

`target`

The username the ICE candidate needs to be delivered to. This lets the signaling server route the message.

`candidate`

The SDP representing the candidate the ICE layer wants to transmit to the other peer.

The format of this message (as is the case with everything you do when handling signaling) is entirely up to you, depending on your needs; you can provide other information as required.

>
> **Note:** It's important to keep in mind that the `icecandidate` (en-US) event is **not** sent when ICE candidates arrive from the other end of the call. Instead, they're sent by your own end of the call so that you can take on the job of transmitting the data over whatever channel you choose. This can be confusing when you're new to WebRTC.
>
>
>

##### Receiving ICE candidates

The signaling server delivers each ICE candidate to the destination peer using whatever method it chooses; in our example this is as JSON objects, with a `type` property containing the string `"new-ice-candidate"`. Our `handleNewICECandidateMsg()` function is called by our main WebSocket incoming message code to handle these messages:

```js
function handleNewICECandidateMsg(msg) {
  const candidate = new RTCIceCandidate(msg.candidate);

  myPeerConnection.addIceCandidate(candidate).catch(reportError);
}
```

This function constructs an `RTCIceCandidate` (en-US) object by passing the received SDP into its constructor, then delivers the candidate to the ICE layer by passing it into `myPeerConnection.addIceCandidate()` (en-US). This hands the fresh ICE candidate to the local ICE layer, and finally, our role in the process of handling this candidate is complete.

Each peer sends to the other peer a candidate for each possible transport configuration that it believes might be viable for the media being exchanged. At some point, the two peers agree that a given candidate is a good choice and they open the connection and begin to share media. It's important to note, however, that ICE negotiation does *not* stop once media is flowing. Instead, candidates may still keep being exchanged after the conversation has begun, either while trying to find a better connection method, or because they were already in transport when the peers successfully established their connection.

In addition, if something happens to cause a change in the streaming scenario, negotiation will begin again, with the `negotiationneeded` (en-US) event being sent to the `RTCPeerConnection`, and the entire process starts again as described before. This can happen in a variety of situations, including:

* Changes in the network status, such as a bandwidth change, transitioning from Wi-Fi to cellular connectivity, or the like.
* Switching between the front and rear cameras on a phone.
* A change to the configuration of the stream, such as its resolution or frame rate.

##### Receiving new streams

When new tracks are added to the `RTCPeerConnection`— either by calling its `addTrack()` (en-US) method or because of renegotiation of the stream's format—a `track` (en-US) event is set to the `RTCPeerConnection` for each track added to the connection. Making use of newly added media requires implementing a handler for the `track` event. A common need is to attach the incoming media to an appropriate HTML element. In our example, we add the track's stream to the `<video>` element that displays the incoming video:

```js
function handleTrackEvent(event) {
  document.getElementById("received\_video").srcObject = event.streams[0];
  document.getElementById("hangup-button").disabled = false;
}
```

The incoming stream is attached to the `"received_video"` `<video>` element, and the "Hang Up" `<button>` element is enabled so the user can hang up the call.

Once this code has completed, finally the video being sent by the other peer is displayed in the local browser window!

##### Handling the removal of tracks

Your code receives a `removetrack` event when the remote peer removes a track from the connection by calling `RTCPeerConnection.removeTrack()` (en-US). Our handler for `"removetrack"` is:

```js
function handleRemoveTrackEvent(event) {
  const stream = document.getElementById("received\_video").srcObject;
  const trackList = stream.getTracks();

  if (trackList.length === 0) {
    closeVideoCall();
  }
}
```

This code fetches the incoming video `MediaStream` from the `"received_video"` `<video>` element's `srcObject` attribute, then calls the stream's `getTracks()` method to get an array of the stream's tracks.

If the array's length is zero, meaning there are no tracks left in the stream, we end the call by calling `closeVideoCall()`. This cleanly restores our app to a state in which it's ready to start or receive another call. See Ending the call to learn how `closeVideoCall()` works.

#### Ending the call

There are many reasons why calls may end. A call might have completed, with one or both sides having hung up. Perhaps a network failure has occurred, or one user might have quit their browser, or had a system crash. In any case, all good things must come to an end.

##### Hanging up

When the user clicks the "Hang Up" button to end the call, the `hangUpCall()` function is called:

```js
function hangUpCall() {
  closeVideoCall();
  sendToServer({
    name: myUsername,
    target: targetUsername,
    type: "hang-up",
  });
}
```

`hangUpCall()` executes `closeVideoCall()` to shut down and reset the connection and release resources. It then builds a `"hang-up"` message and sends it to the other end of the call to tell the other peer to neatly shut itself down.

##### Ending the call

The `closeVideoCall()` function, shown below, is responsible for stopping the streams, cleaning up, and disposing of the `RTCPeerConnection` object:

```js
function closeVideoCall() {
  const remoteVideo = document.getElementById("received\_video");
  const localVideo = document.getElementById("local\_video");

  if (myPeerConnection) {
    myPeerConnection.ontrack = null;
    myPeerConnection.onremovetrack = null;
    myPeerConnection.onremovestream = null;
    myPeerConnection.onicecandidate = null;
    myPeerConnection.oniceconnectionstatechange = null;
    myPeerConnection.onsignalingstatechange = null;
    myPeerConnection.onicegatheringstatechange = null;
    myPeerConnection.onnegotiationneeded = null;

    if (remoteVideo.srcObject) {
      remoteVideo.srcObject.getTracks().forEach((track) => track.stop());
    }

    if (localVideo.srcObject) {
      localVideo.srcObject.getTracks().forEach((track) => track.stop());
    }

    myPeerConnection.close();
    myPeerConnection = null;
  }

  remoteVideo.removeAttribute("src");
  remoteVideo.removeAttribute("srcObject");
  localVideo.removeAttribute("src");
  remoteVideo.removeAttribute("srcObject");

  document.getElementById("hangup-button").disabled = true;
  targetUsername = null;
}
```

After pulling references to the two `<video>` elements, we check if a WebRTC connection exists; if it does, we proceed to disconnect and close the call:

1. All of the event handlers are removed. This prevents stray event handlers from being triggered while the connection is in the process of closing, potentially causing errors.
2. For both remote and local video streams, we iterate over each track, calling the `MediaStreamTrack.stop()` method to close each one.
3. Close the `RTCPeerConnection` by calling `myPeerConnection.close()`.
4. Set `myPeerConnection` to `null`, ensuring our code learns there's no ongoing call; this is useful when the user clicks a name in the user list.

Then for both the incoming and outgoing `<video>` elements, we remove their `src` and `srcObject` attributes using their `removeAttribute()` methods. This completes the disassociation of the streams from the video elements.

Finally, we set the `disabled` property to `true` on the "Hang Up" button, making it unclickable while there is no call underway; then we set `targetUsername` to `null` since we're no longer talking to anyone. This allows the user to call another user, or to receive an incoming call.

#### Dealing with state changes

There are a number of additional events you can set listeners for which notifying your code of a variety of state changes. We use three of them: `iceconnectionstatechange` (en-US), `icegatheringstatechange` (en-US), and `signalingstatechange` (en-US).

##### ICE connection state

`iceconnectionstatechange` (en-US) events are sent to the `RTCPeerConnection` by the ICE layer when the connection state changes (such as when the call is terminated from the other end).

```js
function handleICEConnectionStateChangeEvent(event) {
  switch (myPeerConnection.iceConnectionState) {
    case "closed":
    case "failed":
      closeVideoCall();
      break;
  }
}
```

Here, we apply our `closeVideoCall()` function when the ICE connection state changes to `"closed"` or `"failed"`. This handles shutting down our end of the connection so that we're ready start or accept a call once again.

>
> **Note:** We don't watch the `disconnected` signaling state here as it can indicate temporary issues and may go back to a `connected` state after some time. Watching it would close the video call on any temporary network issue.
>
>
>

##### ICE signaling state

Similarly, we watch for `signalingstatechange` (en-US) events. If the signaling state changes to `closed`, we likewise close the call out.

```js
function handleSignalingStateChangeEvent(event) {
  switch (myPeerConnection.signalingState) {
    case "closed":
      closeVideoCall();
      break;
  }
}
```

>
> **Note:** The `closed` signaling state has been deprecated in favor of the `closed` `iceConnectionState` (en-US). We are watching for it here to add a bit of backward compatibility.
>
>
>

##### ICE gathering state

`icegatheringstatechange` (en-US) events are used to let you know when the ICE candidate gathering process state changes. Our example doesn't use this for anything, but it can be useful to watch these events for debugging purposes, as well as to detect when candidate collection has finished.

```js
function handleICEGatheringStateChangeEvent(event) {
  // Our sample just logs information to console here,
  // but you can do whatever you need.
}
```

Next steps
----------

You can now try out this example on Glitch to see it in action. Open the Web console on both devices and look at the logged output—although you don't see it in the code as shown above, the code on the server (and on GitHub) has a lot of console output so you can see the signaling and connection processes at work.

Another obvious improvement would be to add a "ringing" feature, so that instead of just asking the user for permission to use the camera and microphone, a "User X is calling. Would you like to answer?" prompt appears first.

関連情報
----

* WebRTC API
* Web media technologies
* Guide to media types and formats on the web
* Media Capture and Streams API
* Media Capabilities API (en-US)
* MediaStream Recording API
* The Perfect Negotiation (en-US) pattern


DeviceOrientationEvent: DeviceOrientationEvent() コンストラクター - Web API

DeviceOrientationEvent: DeviceOrientationEvent() コンストラクター
=========================================================

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**`DeviceOrientationEvent()`** コンストラクターは、新しい `DeviceOrientationEvent` オブジェクトを作成します。

構文
--

```js
new DeviceOrientationEvent(type)
new DeviceOrientationEvent(type, options)
```

### 引数

`type`

 文字列で、このイベントの名前です。
 大文字小文字の区別があり、ブラウザーは `deviceorientation` または `deviceorientationabsolute` に設定します。
 後者の場合、 `options.absolute` は常に `true` です。

`options` 省略可

オブジェクトで、 *`Event()` で定義されているプロパティに加え*、以下のプロパティを持つことができます。

`alpha` 省略可

 Z 軸における端末の動きを表す数値で、 0 ～ 360 の範囲の度数で表します。
 既定値は `null` です。

`beta` 省略可

 X 軸における端末の動きを表す数値で、 -180 ～ 180 の範囲の度数で表します。
 これは端末の前後方向の動きを表します。
 既定値は `null` です。

`gamma` 省略可

 X 軸における端末の動きを表す数値で、 -90 ～ 90 の範囲の度数で表します。
 これは端末の左右方向の動きを表します。
 既定値は `null` です。

`absolute`

 論理値で、端末yが絶対に方向データを提供しているかどうかを示します。
 既定値は `false` です。

返値
--

新しい `DeviceOrientationEvent` オブジェクトです。

仕様書
---

| Specification |
| --- |
| DeviceOrientation Event Specification # dom-deviceorientationevent-deviceorientationevent |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


DeviceOrientationEvent: alpha プロパティ - Web API

DeviceOrientationEvent: alpha プロパティ
===================================

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**`alpha`** は `DeviceOrientationEvent` インターフェイスの読み取り専用プロパティで、 Z 軸をの端末の回転を返します。つまり、端末が画面の中央を中心に何度回転したかを返します。
 詳しくは方向および動きとして示されるデータを参照してください。

値
-

数値です。

仕様書
---

| Specification |
| --- |
| DeviceOrientation Event Specification # ref-for-dom-deviceorientationevent-alpha③ |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `DeviceOrientationEvent`
* 端末の方向の検出
* 方向および動きとして示されるデータ
* `deviceorientation` イベント


DeviceOrientationEvent: gamma プロパティ - Web API

DeviceOrientationEvent: gamma プロパティ
===================================

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**`gamma`** は `DeviceOrientationEvent` インターフェイスのプロパティで、 Y 軸における端末の回転、つまり端末が左右に傾いている度数を `-90` から `90` の範囲で返します。
 詳しくは方向および動きとして示されるデータを参照してください。

値
-

数値です。

仕様書
---

| Specification |
| --- |
| DeviceOrientation Event Specification # ref-for-dom-deviceorientationevent-gamma② |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `DeviceOrientationEvent`
* 端末の方向の検出
* 方向および動きとして示されるデータ
* `deviceorientation` イベント


DeviceOrientationEvent: absolute プロパティ - Web API

DeviceOrientationEvent: absolute プロパティ
======================================

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**`absolute`** は `DeviceOrientationEvent` インターフェイスの読み取り専用プロパティで、端末が絶対的に（つまり、地球の座標フレームを参照して）方向データを提供しているのか、それとも端末が決定した任意のフレームを使用しているのかを示します。
 詳しくは方向および動きとして示されるデータを参照してください。

値
-

* `instanceOfDeviceOrientationEvent` の方向データが、地球の座標フレームと端末の座標フレームの差として指定された場合に `true` を返します。
* 方向データが、任意の、端末が決定した座標フレームを参照して提供されている場合は `false` を返します。
仕様書
---

| Specification |
| --- |
| DeviceOrientation Event Specification # ref-for-dom-deviceorientationevent-absolute |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `DeviceOrientationEvent`
* 端末の方向の検出
* 方向および動きとして示されるデータ
* `deviceorientation` イベント


DeviceOrientationEvent: beta プロパティ - Web API

DeviceOrientationEvent: beta プロパティ
==================================

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

**`beta`** は `DeviceOrientationEvent` インターフェイスの読み取り専用プロパティで、 X 軸における端末の回転を返します。つまり、 -180 度から 180 度の範囲で、端末が前方または後方に傾いている度数を返します。
 詳しくは方向および動きとして示されるデータを参照してください。

値
-

数値です。

仕様書
---

| Specification |
| --- |
| DeviceOrientation Event Specification # ref-for-dom-deviceorientationevent-beta② |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `DeviceOrientationEvent`
* 端末の方向の検出
* 方向および動きとして示されるデータ
* `deviceorientation` イベント


TextEncoderStream: writable プロパティ - Web API

TextEncoderStream: writable プロパティ
=================================

**`writable`** は `TextEncoderStream` インターフェイスの読み取り専用プロパティで、`WritableStream` を返します。

値
-

`WritableStream` です。

例
-

次の例は、`WritableStream` を `TextEncoderStream` オブジェクトから返す方法を示しています。

```js
stream = new TextEncoderStream();
console.log(stream.writable); // WritableStream
```

仕様書
---

| Specification |
| --- |
| Streams Standard # dom-generictransformstream-writable |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextEncoderStream: readable プロパティ - Web API

TextEncoderStream: readable プロパティ
=================================

**`readable`** は `TextEncoderStream` インターフェイスの読み取り専用プロパティで、`ReadableStream` を返します。

値
-

`ReadableStream` です。

例
-

次の例は、`ReadableStream` を `TextEncoderStream` オブジェクトから返す方法を示しています。

```js
stream = new TextEncoderStream();
console.log(stream.readable); // ReadableStream
```

仕様書
---

| Specification |
| --- |
| Streams Standard # dom-generictransformstream-readable |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextEncoderStream: TextEncoderStream() コンストラクター - Web API

TextEncoderStream: TextEncoderStream() コンストラクター
===============================================

**`TextEncoderStream()`** コンストラクター、文字列のストリームを UTF-8 エンコーディングを使用してバイト列に変換するために使用する、新しい `TextEncoderStream` オブジェクトを作成します。

構文
--

```js
new TextEncoderStream()
```

### 引数

なし。

例
-

この例では、`TextEncoderStream` を作成してテキストのストリームのアップロードに使用しています。

```js
const body = textStream.pipeThrough(new TextEncoderStream());
fetch("/dest", {
  method: "POST",
  body,
  headers: { "Content-Type": "text/plain; charset=UTF-8" },
});
```

仕様書
---

| Specification |
| --- |
| Encoding Standard # ref-for-dom-textencoderstream① |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


TextEncoderStream: encoding プロパティ - Web API

TextEncoderStream: encoding プロパティ
=================================

**`encoding`** は `TextEncoderStream` インターフェイスの読み取り専用プロパティで、現在の `TextEncoderStream` オブジェクトが使用するエンコーディングアルゴリズムの名前が入った文字列を返します。

値
-

`utf-8` のエンコードされたデータが入った文字列です。

例
-

以下の例は、`TextEncoderStream` オブジェクトが `encoding` を返す方法を示しています。

```js
stream = new TextEncoderStream();
console.log(stream.encoding);
```

仕様書
---

| Specification |
| --- |
| Encoding Standard # dom-textencoder-encoding |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLTableRowElement: rowIndex プロパティ - Web API

HTMLTableRowElement: rowIndex プロパティ
===================================

**`HTMLTableRowElement.rowIndex`** は読み取り専用プロパティで、表 (`<table>`) 全体に対する行の相対的な位置を表します。

`<thead>`、`<tbody>`、`<tfoot>` の各要素が HTML の中で順不同であっても、ブラウザーは表を正しい順序で描画します。従って行のカウントは `<thead>` から `<tbody>` へ、 `<tbody>` から `<tfoot>` へと進みます。

値
-

行の位置を返します。行が表に所属していない場合は `-1` です。

例
-

この例は、 JavaScript を使用して表のすべての行に行番号を振ります。

### HTML

```html
<table>
  <thead>
    <tr>
      <th>品目</th>
      <th>価格</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>バナナ</td>
      <td>$2</td>
    </tr>
    <tr>
      <td>オレンジ</td>
      <td>$8</td>
    </tr>
    <tr>
      <td>トップサーロイン</td>
      <td>$20</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <td>合計</td>
      <td>$30</td>
    </tr>
  </tfoot>
</table>
```

### JavaScript

```js
let rows = document.querySelectorAll("tr");

rows.forEach((row) => {
  let z = document.createElement("td");
  z.textContent = `(#${row.rowIndex} 行目)`;
  row.appendChild(z);
});
```

### 結果

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


HTMLTableRowElement: insertCell() メソッド - Web API

HTMLTableRowElement: insertCell() メソッド
======================================

**`HTMLTableRowElement.insertCell()`** メソッドは、新しいセル (`<td>`) を表の行 (`<tr>`) に挿入し、そのセルの参照を返します。

**メモ:** `insertCell()` はセルを直接行に挿入します。 `Document.createElement()` を使用して新しい `<td>` 要素を作成した場合のように、 `Node.appendChild()` を使用して個別にセルを追加する必要はありません。

ただし、 `insertCell()` を使用して新しい `<th>` 要素を作成することはできません。

構文
--

```js
insertCell()
insertCell(index)
```

`HTMLTableRowElement` は HTML の `<tr>` 要素への参照です。

### 引数

`index` 省略可

新しいセルの位置を指定します。 `index` が `-1` またはセル数と等しい場合、そのセルは行の最後のセルとして追加されます。 `index` が省略された場合は、既定で `-1` となります。

### 返値

`HTMLTableCellElement` で、新しいセルへの参照です。

### 例外

`IndexSizeError` `DOMException`

`index` がセル数よりも大きい場合に発生します。

例
-

この例では、 `HTMLTableElement.insertRow()` を使用して表に新しい行を追加します。

それから `insertCell(0)` を使用して、新しいセルを新しい行に追加します。（有効な HTML にするためには、 `<tr>` は 1 つ以上の `<td>` 要素を持つ必要があります。）最後に、 `Document.createTextNode()` と `Node.appendChild()` を使用していくらかのテキストを追加します。

### HTML

```html
<table id="my-table">
  <tr>
    <td>行 1</td>
  </tr>
  <tr>
    <td>行 2</td>
  </tr>
  <tr>
    <td>行 3</td>
  </tr>
</table>
```

### JavaScript

```js
function addRow(tableID) {
  // 表への参照を取得
  let tableRef = document.getElementById(tableID);

  // 表の末尾に行を追加
  let newRow = tableRef.insertRow(-1);

  // 行の 0 の位置にセルを追加
  let newCell = newRow.insertCell(0);

  // セルにテキストノードを追加
  let newText = document.createTextNode("新しい最下行");
  newCell.appendChild(newText);
}

// addRow() を表の ID で呼び出す
addRow("my-table");
```

### 結果

仕様書
---

| Specification |
| --- |
| HTML Standard # dom-tr-insertcell-dev |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `HTMLTableElement.insertRow()`
* セルを表す HTML 要素: `HTMLTableCellElement`


MediaStreamTrack.label - Web API

MediaStreamTrack.label
======================

**`MediaStreamTrack.label`** は読み取り専用のプロパティであり、トラックのソースを識別するためにユーザーエージェントによって割り当てられたラベルを含む文字列を返します。例えば `"internal microphone"` などです。

この文字列は空になることもあり、ソースが接続されていないと空になります。トラックのソースとの関連付けが解除されても、このラベルは変更されません。

構文
--

```js
const label = track.label;
```

仕様書
---

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-label |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebRTC


MediaStreamTrack.enabled - Web API

MediaStreamTrack.enabled
========================

**`enabled`** は `MediaStreamTrack` インターフェイスのプロパティで、このトラックがソースストリームから出力が許可されている場合は `true`、そうでない場合は `false` となる論理値です。これは意図的にトラックをミュートするために使用することができます。

有効な場合、トラックのデータはソースから出力先に出力され、そうでない場合は空のフレームが出力されます。

音声の場合、無効なトラックは無音の（つまり、すべてのサンプルの値が 0 であるフレーム）を生成します。動画トラックでは、すべてのフレームが黒いピクセルで完全に埋められます。

一方 `muted` プロパティは、トラックが一時的にデータを出力できない状態（転送中にフレームが失われた場合など）を示しています。

**メモ:** トラックが接続されていない場合でも、このプロパティの値は変更可能ですが、効果はありません。

値
-

`true` の場合、 `enabled` はそのトラックが実際のメディアを出力にレンダリングすることが許可されていることを示します。 `enabled` が `false` に設定されている場合、トラックは空のフレームのみを生成します。

空のオーディオフレームは、すべてのサンプルの値が 0 に設定されます。空のビデオフレームは、すべてのピクセルが黒に設定されます。

**メモ:** ミュート/ミュート解除機能を実装する場合は、 `enabled` プロパティを使用してください。

使用上のメモ
------

この `MediaStreamTrack` がカメラからの動画入力を表している場合、 `enabled` を `false` に設定してトラックを無効にすると、カメラが現在録画やストリーミングをしていないことを示すデバイスアクティビティインジケーターも更新されます。例えば、 iMac や MacBook コンピューターでは、この方法でトラックをミュートしている間、カメラの横にある緑の「使用中」ランプが消灯します。

例
-

この例では、一時停止ボタンの `click` イベントハンドラーの使用例を示しています。

```js
pauseButton.onclick = function (evt) {
  const newState = !myAudioTrack.enabled;

  pauseButton.innerHTML = newState ? "▶" : "⏸";
  myAudioTrack.enabled = newState;
};
```

これは、現在の `enabled` の値と逆の値である `newState` という変数を作成し、それを使用して、一時停止ボタンの要素の新しい `innerHTML` として "play" アイコンまたは "pause" アイコン用の絵文字を選択するものです。

最後に、新しい値を `enabled` に保存し、変更が有効になります。

仕様書
---

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-enabled |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* MediaStream API
* `MediaStream`
* `MediaStreamTrack`
* WebRTC


MediaStreamTrack.id - Web API

MediaStreamTrack.id
===================

**`MediaStreamTrack.id`** は読み取り専用のプロパティであり、このトラックのための固有識別子 (GUID)を含む文字列を返します。この値はユーザーエージェントによって生成されます。

構文
--

```js
const id = track.id;
```

仕様書
---

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-id |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebRTC


MediaStreamTrack.kind - Web API

MediaStreamTrack.kind
=====================

**`MediaStreamTrack.kind`** は読み取り専用のプロパティであり、トラックの種類を示す文字列を返します。トラックが音声トラックの場合は `"audio"` を返し、映像トラックの場合は `"video"` を返します。トラックがソースから切り離されている場合は、何も変更されません。

値
-

有効な値は、以下のいずれかの値を取る文字列です。

* `"audio"`: このトラックは音声トラックです。
* `"video"`: このトラックは映像トラックです。
仕様書
---

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-kind |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* WebRTC


MediaStreamTrack.readyState - Web API

MediaStreamTrack.readyState
===========================

**`MediaStreamTrack.readyState`** は読み取り専用のプロパティであり、トラックの状態を表す列挙値を返します。

値
-

以下の値の何れかを取ります。

* `"live"` は、入力が接続され、リアルタイムなデータがベストエフォートで提供されている状態を示します。この状態では、データの出力は、 `MediaStreamTrack.enabled` プロパティを用いて、オン/オフを切り替えることができます。
* `"ended"` は、入力がこれ以上データを提供せず、新しいデータも提供しないことを示します。
仕様書
---

| Specification |
| --- |
| Media Capture and Streams # dom-mediastreamtrack-readystate |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* Media Stream API
* WebRTC
* `ended` イベント