## 1. Project Overview & Quickstart (flutter-webrtc/CONTRIBUTING)

# CONTRIBUTING

Open-source repository flutter-webrtc/CONTRIBUTING

### Repository Details
- **Repository:** [flutter-webrtc/CONTRIBUTING](https://github.com/flutter-webrtc/CONTRIBUTING)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (flutter-webrtc/docs)

## File: README.md

# Website

flutter-webrtc community official website, built-in documentation & tutorials.

https://flutter-webrtc.org


This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.

## Installation

```console
yarn install
```

## Local Development

```console
yarn start
```

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

## Build

```console
yarn build
```

This command generates static content into the `build` directory and can be served using any static contents hosting service.

## Deployment

```console
GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
```

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.

## i18n

```console
npm run write-translations -- --locale zh-cn
```

```console
npm run start -- --locale zh-cn
```

---

## File: docs/dart-sip-ua/introduction.md

---
sidebar_position: 1
---

# Introduction

Dart SIP UA is a SIP protocol stack developed by dart-lang. You can use it to develop cross-platform VOIP applications. This project relies on the flutter-webrtc plugin, so you can get a high-quality audio and video call experience. SIP signaling uses WSS ( WebSocket Secure), all data is encrypted, you don't need to worry about eavesdropping on the call.

## Overview

- Use pure [dart-lang](https://dart.dev)
- SIP over WebSocket (use real SIP in your flutter mobile, [desktop](https://flutter.dev/desktop), [web](https://flutter.dev/web) apps)
- High-quality Audio/video calls ([flutter-webrtc](https://github.com/cloudwebrtc/flutter-webrtc)) and instant messaging
- Support with standard SIP servers such as OpenSIPS, Kamailio, Asterisk and FreeSWITCH.
- Support RFC2833 or INFO to send DTMF.

## Thanks

Thanks to the original authors of [JsSIP](https://github.com/versatica/JsSIP) for developed the JS version, which makes it possible to port the [dart-lang](https://dart.dev) version.

- [José Luis Millán](https://github.com/jmillan)
- [Iñaki Baz Castillo](https://github.com/ibc)
- [Saúl Ibarra Corretgé](https://github.com/saghul)

## Sponsors

The first version was sponsored by Suretec Systems Ltd. T/A [SureVoIP](https://www.surevoip.co.uk).

---

## File: docs/flutter-webrtc/api-docs/get-display-media.md

---
sidebar_position: 3
---

# GetDisplayMedia

The `getDisplayMedia` method of the `MediaDevices` interface prompts the user to select and grant permission to capture the contents of a display or portion thereof (such as a window or screen) as a `MediaStream`.

The corresponding JS API docs is here [MediaDevices.getDisplayMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia).

## Usage

```dart
MediaStream stream = await navigator.mediaDevices.getDisplayMedia({
  'video': true,
  'audio': true,
});
```

## Parameters

- `audio`: A Boolean value that indicates whether the `MediaStream` should include an audio track.
         audio is optional, default is false. only chrome tabs can support audio caputure.

- `video`: A Boolean value that indicates whether the `MediaStream` should include a video track.
         video is optional, default is true.

---

## File: docs/flutter-webrtc/api-docs/get-user-media.md

---
sidebar_position: 2
---

# GetUserMedia

The corresponding JS API docs is here
[MediaDevices.getUserMedia()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia).

## Usage

basic usage:

```dart
await navigator.mediaDevices.getUserMedia({'audio': true, 'video': true});
```

advanced usage:

```dart
await navigator.mediaDevices.getUserMedia({
  'audio': true,
  'video': {
    'facingMode': 'user', // or 'environment' for mobile devices
    'width': 1280,
    'height': 720,
    'frameRate': 30,
  }
});
```

## Parameters

- mediaConstraints: A dictionary object that specifies the media constraints for the requested media types.
refer to the [MediaStreamConstraints](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints) for more details.

sub options:

- `audio`: A Boolean value that indicates whether the MediaStream should include an audio track.

or a dictionary object that specifies the audio track's media constraints.

```json
{
    'deviceId': 'audio_device_id',
}
```

- `video`: A Boolean value that indicates whether the MediaStream should include a video track.

or a dictionary object that specifies the video track's media constraints.

```json
{
    'deviceId': 'video_device_id',
    'facingMode': 'user', // or 'environment' for mobile devices
    'width': 1280,
    'height': 720,
    'frameRate': 30,
}
```

## Return value

A Promise that resolves to a MediaStream object.

Note: The `deviceId` parameter is used to specify the device to use. If you want to use the default device, you can omit this parameter. If you want to use a specific device, you can get the device ID by calling `navigator.mediaDevices.enumerateDevices` [here](./media-devices) and then pass it to the `deviceId` parameter.

---

## File: docs/flutter-webrtc/api-docs/media-devices.md

---
sidebar_position: 1
---

# MediaDevices

The corresponding JS API docs is here [MediaDevices](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices).

## Usage

```dart
MediaDevices mediaDevices = await navigator.mediaDevices;

MediaStream stream = await mediaDevices.getUserMedia({
  'audio': true,
  'video': true,
});

MediaStream displayStream = await mediaDevices.getDisplayMedia({
  'video': true,
  'audio': true,
});

List<MediaDeviceInfo> devices = await mediaDevices.enumerateDevices();

```

## Methods

- `getUserMedia`: Returns a Promise that resolves to a `MediaStream` object. The `MediaStream` object represents a stream of media content, typically (but not necessarily) including both audio and video.

```dart
MediaStream stream = await mediaDevices.getUserMedia({
  'audio': true,
  'video': true,
});
```

- `getDisplayMedia`: Returns a Promise that resolves to a `MediaStream` object. The `MediaStream` object represents a stream of media content, typically (but not necessarily) including both audio and video.

```dart
MediaStream stream = await mediaDevices.getDisplayMedia({
  'video': true,
  'audio': true,
});
```

- `enumerateDevices`: Returns a Promise that resolves to an array of `MediaDeviceInfo` objects, each of which represents a media input or output device.

```dart
List<MediaDeviceInfo> devices = await mediaDevices.enumerateDevices();
```

- `getSupportedConstraints`: Returns a dictionary object that specifies the media constraints supported by the user agent.
    only support for web platform.

- `selectAudioOutput`: select audio output device.
    support platforms: macOS/Windows/Linux/Web.

## Event Callbacks

- `onDeviceChange`: The `ondevicechange` event handler for the `MediaDevices` interface. It is called when a media input or output device is attached or removed.

---

## File: docs/flutter-webrtc/api-docs/media-recorder.md

---
sidebar_position: 7
---

# MediaRecorder

The corresponding JS API docs is here [MediaRecorder](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder).

Creates a new `MediaRecorder` object, given a MediaStream to record. Options are available to do things like set the container's MIME type (such as "video/webm" or "video/mp4") and the bit rates of the audio and video tracks or a single overall bit rate.

## Methods

- `start`: Starts recording the media.
           For Android use audioChannel param.
           For iOS use audioTrack.

```dart
void start() async {
    if (Platform.isIOS) {
      print('Recording is not available on iOS');
      return;
    }
    // TODO(rostopira): request write storage permission
    final storagePath = await getExternalStorageDirectory();
    if (storagePath == null) throw Exception('Can\'t find storagePath');

    final filePath = storagePath.path + '/webrtc_sample/test.mp4';
    mediaRecorder = MediaRecorder();
    setState(() {});
    final videoTrack = stream
        .getVideoTracks().first;
    await mediaRecorder.start(
      filePath,
      videoTrack: videoTrack,
      audioChannel: RecorderAudioChannel.INPUT,
    );
  }
```

- `startWeb`: Starts recording the media in the web.only for flutter web.

```dart
void startWeb() async {
    mediaRecorder = MediaRecorder();
    setState(() {});
    mediaRecorder.startWeb(stream,onDataChunk:(data){
        // do something with data
        dynamic blob, bool isLastOne
    } ,'video/webm', 1000);
  }
```

- `stop`: Stops recording the media.

```dart
void stop() async {
    await mediaRecorder.stop();
    setState(() {
      mediaRecorder = null;
    });
  }
```

---

## File: docs/flutter-webrtc/api-docs/media-stream.md

---
sidebar_position: 8
---

# MediaStream

The corresponding JS API docs is here [MediaStream](https://developer.mozilla.org/en-US/docs/Web/API/MediaStream).

The MediaStream interface of the Media Capture and Streams API represents a stream of media content. A stream consists of several tracks, such as video or audio tracks. Each track is specified as an instance of MediaStreamTrack.

## Methods

- `addTrack`:Adds the given `MediaStreamTrack` to this `MediaStream`.

```dart
var mediaStream = MediaStream(
    id: 'audio-stream',
    ownerTag: 'audio-tag',
    active: true,
/// The active attribute return true if this [MediaStream] is active and false otherwise.
/// [MediaStream] is considered active if at least one of its [MediaStreamTracks] is not in the [MediaStreamTrack.ended] state.
/// Once every track has ended, the stream's active property becomes false.
    onAddTrack: (MediaStreamTrack track) {
      print('Track added: ${track.id}');
    },
    onRemoveTrack: (MediaStreamTrack track) {
      print('Track removed: ${track.id}');
    },
);
mediaStream.addTrack(track, {addToNative: true});
```

- `removeTrack`:Removes the given `MediaStreamTrack` object from this `MediaStream`.

```dart
mediaStream.removeTrack(track,{removeFromNative: true});
```

- `getTracks`:Returns a List `MediaStreamTrack` objects representing all the tracks in this stream.

```dart
var tracks = mediaStream.getTracks();
```

- `getAudioTracks`:Returns a List `MediaStreamTrack` objects representing the audio tracks in this stream.
The list represents a snapshot of all the `MediaStreamTrack` objects in this stream's track set whose kind is equal to 'audio'.

```dart
var audioTracks = mediaStream.getAudioTracks();
```

- `getVideoTracks`:Returns a List `MediaStreamTrack` objects representing the video tracks in this stream.

```dart
var videoTracks = mediaStream.getVideoTracks();
```

- `getTrackById`:Returns either a `MediaStreamTrack` object from this stream's track set whose id is equal to trackId, or `StateError`, if no such track exists.

```dart
var track = mediaStream.getTrackById('some-track-id');
```

- `dispose`:Dispose the `MediaStream`.

```dart
await mediaStream.dispose();
```

## Events

- `onAddTrack`:Fires when a new `MediaStreamTrack` is added to this `MediaStream`.

```dart
var mediaStream = MediaStream(
    id: 'audio-stream',
    ownerTag: 'audio-tag',
    active: true,
);
mediaStream.onAddTrack = (MediaStreamTrack track) {
  print('Track added: ${track.id}');
};
```

- `onRemoveTrack`:Fires when a `MediaStreamTrack` is removed from this `MediaStream`.

```dart
var mediaStream = MediaStream(
    id: 'audio-stream',
    ownerTag: 'audio-tag',
    active: true,
);
mediaStream.onRemoveTrack = (MediaStreamTrack track) {
  print('Track removed: ${track.id}');
};
```

---

## File: docs/flutter-webrtc/api-docs/media-stream-track.md

---
sidebar_position: 6
---

# MediaStreamTrack

The corresponding JS API docs is here [MediaStreamTrack](https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack).

The `MediaStreamTrack` interface represents a single media track within a stream; typically, these are audio or video tracks, but other track types may exist as well. A `MediaStreamTrack` can be associated with multiple `MediaStream` objects.

## Methods

- `stop`: Stops the track.

```dart
void stopStreamedVideo(RTCVideoRenderer renderer) {
  var stream = renderer.srcObject;
  var tracks = stream.getTracks();

  tracks.forEach((track) => {
    track.stop();
  });

  randerer.srcObject = null;
}
```

## Events

- `onMute`: Sent to the MediaStreamTrack when the value of the muted property is changed to true, indicating that the track is unable to provide data temporarily (such as when the network is experiencing a service malfunction).

```dart
track.onMute = (event) {
  print("Track ${track.id} is muted");
};
```

- `onUnMute`: Sent to the MediaStreamTrack when the value of the muted property is changed to false, indicating that the track is able to provide data again (such as when the network is no longer experiencing a service malfunction).

```dart
track.onUnMute = (event) {
  print("Track ${track.id} is unmuted");
};
```

- `onEnded`:Sent when playback of the track ends (when the value readyState changes to ended), except when the track is ended by calling MediaStreamTrack.stop.

```dart
track.onEnded = (event) {
  print("Track ${track.id} has ended");
};
```

## Properties

- `id`: Returns the unique identifier of the track.

- `label`:This may label audio and video sources (e.g., "Internal microphone" or "External USB     Webcam"). Returns the label of the object's corresponding source, if any.
          If the corresponding source has or had no label, returns an empty string.

- `kind`: Returns the type of track, such as "audio" or "video".

- `enabled`: Returns the enable state of `MediaStreamTrack`.After a `MediaStreamTrack` has ended, setting the enable state
will not change the ended state.

- `muted`: Returns true if the track is muted, and false otherwise.

---

## File: docs/flutter-webrtc/api-docs/rtc-data-channel.md

---
sidebar_position: 9
---

# RTCDataChannel

The corresponding JS API docs is here [RTCDataChannel](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel).

The RTCDataChannel interface represents a network channel which can be used for bidirectional peer-to-peer transfers of arbitrary data. Every data channel is associated with an RTCPeerConnection, and each peer connection can have up to a theoretical maximum of 65,534 data channels (the actual limit may vary from browser to browser).

## Methods

- `send`:Send a message to this datachannel.
To send a text message, use the default constructor to instantiate a text [RTCDataChannelMessage]for the [message] parameter.
To send a binary message, pass a binary [RTCDataChannelMessage].
constructed with [RTCDataChannelMessage.fromBinary].

```dart
var sendChannel = await pc.createDataChannel(
     'dataChannel',
     dataChannelDict,
    );
sendChannel.send('Hello, world!');
```

- `close`:Close the data channel.

```dart
sendChannel.close();
```

## Properties

- `id`:The unique identifier of the data channel.

- `label`:The label of the data channel.

- `state`:The current state of the data channel.

- `bufferedAmount`:The number of bytes of data currently queued to be sent over the data channel.

- `bufferedAmountLowThreshold`:Set threshold to trigger onBufferedAmountLow callback.

## Events

- `onDataChannelState`:Stream of state change events. Emits the new state on change.
Closes when the [RTCDataChannel] is closed.

```dart
var dc = await pc.createDataChannel('dataChannel');
dataChannel.onDataChannelState(state) {
    print('Data channel state is: $state');
};
/// or
dataChannel.stateChangeStream.listen((state) {
    print('Data channel state is: $state');
});
```

- `onMessage`:Stream of incoming messages. Emits the [RTCDataChannelMessage] on message.

```dart
dataChannel.onMessage(data) {
    print('Received data: $data.text');
};
/// or
dataChannel.messageStream.listen((data) {
    print('Received data: $data.text');
});
```

- `onBufferedAmountChange`:Stream of buffered amount change events.

```dart
dataChannel.onBufferedAmountChange(int currentAmount, int changedAmount) {
    print('Buffered amount change: $changedAmount');
};
```

- `onBufferedAmountLow`:Stream of low buffer amount events.

```dart
dataChannel.onBufferedAmountLow(int currentAmount) {
    print('Buffered amount low: $currentAmount');
};

---

## File: docs/flutter-webrtc/api-docs/rtc-dtmf-sender.md

---
sidebar_position: 10
---

# RTCDTMFSender

The corresponding JS API docs is here [RTCDTMFSender](https://developer.mozilla.org/en-US/docs/Web/API/RTCDTMFSender).

The RTCDTMFSender interface provides a mechanism for transmitting DTMF codes on a WebRTC RTCPeerConnection. You gain access to the connection's RTCDTMFSender through the RTCRtpSender.dtmf property on the audio track you wish to send DTMF with.

## Methods

- `insertDTMF`: Sends DTMF tones.

```dart
var dtmfSender = pc.getSenders().firstWhere((s) => s.track.kind == 'audio');
dtmfSender.insertDTMF('1234#', duration: 100, interToneGap: 70);
```

- `canInsertDtmf`: Returns a boolean indicating whether the DTMF sender can send DTMF tones.

```dart
dtmfSender.canInsertDtmf(); /// Return true or false
```

## Properties

- `tones`:A String containing the DTMF codes to be transmitted to the recipient.
          Specifying an empty string as the tones parameter clears the tone
buffer, aborting any currently queued tones. A "," character inserts
a two second delay.

- `duration`:This value must be between 40 ms and 6000 ms (6 seconds).
             The default is 100 ms.

- `interToneGap`:The length of time, in milliseconds, to wait between tones.
                 The browser will enforce a minimum value of 30 ms (that is,
if you specify a lower value, 30 ms will be used instead);
the default is 70 ms.