Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This proposal describes additions and suggested changes to the Media Capture and Streams specification in order to support the goal of device settings retrieval and modification. This proposal incorporates feedback from the W3C TPAC 2012 event and builds on four prior proposals with the same goal [v4] [v3] [v2] [v1].
LocalMediaStream
interfaceLocalMediaStream
interfaceIn this proposal, the derived LocalMediaStream interface is removed. Rather than returning a LocalMediaStream instance in the NavigatorUserMediaSuccessCallback, a vanilla MediaStream object is returned. The primary difference is in the tracks contained in that MediaStream object.
Some feedback even suggested re-considering the "at most one video/audio track per request to getUserMedia".
While thinking about these goals and the feedback, I began to consider a few things:
To illustrate this challenge, consider how my prior proposal required a re-hookup of the MediaStream to a video tag consumer:
Note that this process has to bind a completely new LocalMediaStream to the video tag a second time (if re-using the same video tag) only because the second LocalMediaStream object was different than the first.
It is much more efficient for developer code to simply add/remove tracks to a MediaStream that are relevant, without needing to change the consumer of the MediaStream.
With changes to getUserMedia
to support a synchronous API, this proposal enables developer code to
directly create Media Stream Tracks. It also introduces the concept of the "new"
readyState for tracks,
a state which signals that the specified track is not connected to a source.
All tracks now have a source
attribute, which is used to access a source object. The source object can be
used to read additional settings about the source (content) of a track and to alter the source (content) of the track.
This proposal describes local media device sources (cameras and microphones), and a skeleton description for a
remote media device source (tracks that originate from a peer connection). Media device source objects are described
in the next section.
Below is the new track hierarchy. It is somewhat simplified due to the exclusion of source objects:
This section defines MediaStreamTrack in order to add the new "new"
state and associated
event handlers. The definition is otherwise
identical to the current definition except that the defined constants are replaced by strings (using an enumerated type).
MediaStreamTrack
interfaceinterface MediaStreamTrack : EventTarget {
attribute DOMString id;
readonly attribute DOMString kind;
readonly attribute DOMString label;
attribute boolean enabled;
readonly attribute TrackReadyStateEnum
readyState;
attribute EventHandler onstart;
attribute EventHandler onmute;
attribute EventHandler onunmute;
attribute EventHandler onended;
};
id
of type DOMStringgetTrackById
. (This is a preliminary definition, but is
expected in the latest editor's draft soon.)
kind
of type DOMString, readonlylabel
of type DOMString, readonlyenabled
of type booleanreadyState
of type TrackReadyStateEnum
, readonly"new"
state after being instantiated.
State transitions are as follows:
onstart
of type EventHandlerstart
event. The start
event is fired when this track transitions
from the "new"
state to the "live"
state.
Issue: When working with multiple "new"
tracks, I found that I wanted to have a more centralized
place to be notified when getUserMedia would activate all the tracks in a media stream. Perhaps there's a convenience handler
somewhere else, for example on the MediaStream? There's some work flows to consider here before landing a final design...
onmute
of type EventHandleronunmute
of type EventHandleronended
of type EventHandlerenum TrackReadyStateEnum {
"new",
"live",
"muted",
"ended"
};
Enumeration description | |
---|---|
new | The track type is new and has not been initialized (connected to a source of any kind). This state implies that the track's label will be the empty string. |
live | See the definition of the LIVE constant in the current editor's draft. |
muted | See the definition of the MUTED constant in the current editor's draft. |
ended | See the definition of the ENDED constant in the current editor's draft. |
MediaStreamTrack objects cannot be instantiated directly. To create an instance of a MediaStreamTrack, one of its derived track types may be instantiated directly. These derived types are defined in this section. Each of these track types has general IDL attributes specific to all tracks of the given type as well as a mechanism to obtain the device object that is providing the source for this track.
Note: I'm intentionally keeping these interfaces as sparse as possible. Features of the video/audio tracks that are settings (generally mutable) have been moved to the track's device source instead.
It's important to note that the camera's green light
doesn't come on when a new track is created; nor does the user get
prompted to enable the camera/microphone. Those actions only happen after the developer has requested that a media stream containing
"new"
tracks be bound to a source via getUserMedia
. Until that point tracks are inert.
VideoStreamTrack
interfaceVideoStreamTrack objects are of kind
"video".
Example: VideoStreamTrack objects are instantiated in JavaScript using the new operator:
new VideoStreamTrack();
Issue: It's been suggested that these track constructors can take optional constraints. Such constraints could be stored until activated by getUserMedia to help the user select what characteristics to use when pre-configuring a device source and attaching it to the track. These are not added in this proposal, but could be added later-on.
[Constructor]
interface VideoStreamTrack : MediaStreamTrack
{
readonly attribute VideoFacingEnum
facing;
readonly attribute VideoStreamSource
? source;
};
facing
of type VideoFacingEnum
, readonlyreadyState
is "new"
,
the value "unknown"
is returned.
source
of type VideoStreamSource
, readonly, nullablenull
. When a VideoStreamTrack is first
created, and while it remains in the "new"
state, the source
attribute must return null
.
AudioStreamTrack
interfaceAudioStreamTrack objects are of kind
"audio".
Example: AudioStreamTrack objects are instantiated in JavaScript using the new operator:
new AudioStreamTrack();
[Constructor]
interface AudioStreamTrack : MediaStreamTrack
{
readonly attribute unsigned long level;
readonly attribute AudioStreamSource
? source;
};
level
of type unsigned long, readonly"new"
state. The relative strength (amplitude) of the level is proportional to the gain
of the
audio source device (e.g., to increase the pick-up of the microphone, increase the gain setting).
source
of type AudioStreamSource
, readonly, nullablenull
. When an AudioStreamTrack
is first created, and while it remains in the "new"
state, the source
attribute must return null
.
VideoStreamSource and AudioStreamSource objects are instantiated by the user agent to represent a source that is providing the
media for a MediaStreamTrack. The association of a source object with a media track occurs asynchronously after
permission for use of the track has been requested by getUserMedia
. When the user agent has attached
the source of a MediaStreamTrack, the source object can be accessed via that track's source
attribute.
Note: Some MediaStreamTracks may not provide a source
object; for
example, if the source is coming from an encrypted media source, or a local file source.
Issue: Need to define whether source objects are singletons. For example, if one track adds an expando property onto a source object, will another track that has that same source see the expando on its source object?
VideoStreamSource and AudioStreamSource objects are created by the user agent to represent a camera or microphone device/source for which the source attributes can be inspected and/or changed. At the moment these are limited to local cameras, local microphones, and peer connection sources, but additional sources can be defined later (such a local file system sources for images or audio files).
VideoStreamSource
interfaceinterface VideoStreamSource : EventTarget {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
readonly attribute float frameRate;
readonly attribute VideoRotationEnum
rotation;
readonly attribute VideoMirrorEnum
mirror;
readonly attribute float zoom;
readonly attribute VideoFocusModeEnum
focusMode;
readonly attribute VideoFillLightModeEnum
fillLightMode;
void stop ();
static unsigned long getNumDevices ();
};
width
of type unsigned long, readonly<video>
element sink used
to preview this track would report a width of 768 pixels (the effective width with rotation factored in).
height
of type unsigned long, readonlyframeRate
of type float, readonlyrotation
of type VideoRotationEnum
, readonlymirror
of type VideoMirrorEnum
, readonlyzoom
of type float, readonlyfocusMode
of type VideoFocusModeEnum
, readonlyfillLightMode
of type VideoFillLightModeEnum
, readonlystop
ended
state. Same behavior of the old LocalMediaStream's
stop API, but only affects this track source.
void
getNumDevices
, staticgetUserMedia
.
Issue: This information deliberately adds to the fingerprinting surface of the UA. However, this information
could also be obtained via other round-about techniques using getUserMedia
. This editor deems it worthwhile directly providing
this data as it seems important for determining whether multiple devices of this type are available.
Issue: The ability to be notified when new devices become available has been dropped from this proposal (it was available in v4 via the DeviceList object).
unsigned long
enum VideoFacingEnum {
"unknown",
"user",
"environment"
};
Enumeration description | |
---|---|
unknown | The relative directionality of the camera cannot be determined by the user agent based on the hardware. |
user | The camera is facing toward the user (a self-view camera). |
environment | The camera is facing away from the user (viewing the environment). |
enum VideoRotationEnum {
"0",
"90",
"180",
"270"
};
Enumeration description | |
---|---|
0 | No effective rotation applied (default value if no rotation is supported by the device software). |
90 | A rotation of 90 degrees counter-clockwise (270 degrees in a clockwise rotation). |
180 | A rotation of 180 degrees. |
270 | A rotation of 270 degrees counter-clockwise (90 degrees in a clockwise rotation). |
enum VideoMirrorEnum {
"none",
"horizontal",
"vertical"
};
Enumeration description | |
---|---|
none | No effective mirroring is being applied (default value if no mirroring is supported by the device software). |
horizontal | The image is mirrored along the camera's width value. This setting does not consider the camera's current rotation, so if a 90 degree rotation was also applied to this source, then the "horizontal" mirroring would appear to be a vertical mirroring in a given sink. |
vertical | The image is mirrored along the camera's height value. This setting does not consider the camera's current rotation, so if a 90 degree rotation was also applied to this source, then the "vertical" mirroring would appear to be a horizontal mirroring in a given sink. |
enum VideoFocusModeEnum {
"notavailable",
"auto",
"manual"
};
Enumeration description | |
---|---|
notavailable | This camera does not have an option to change focus modes. |
auto | The camera auto-focuses. |
manual | The camera must be manually focused. |
enum VideoFillLightModeEnum {
"notavailable",
"auto",
"off",
"flash",
"on"
};
Enumeration description | |
---|---|
notavailable | This video device does not have an option to change fill light modes (e.g., the camera does not have a flash). |
auto | The video device's fill light will be enabled when required (typically low light conditions). Otherwise it will be
off. Note that auto does not guarantee that a flash will fire when takePicture is called.
Use flash to guarantee firing of the flash for the takePicture API. auto is the initial value.
|
off | The video device's fill light and/or flash will not be used. |
flash | If the video device is a camera supporting high-resolution photo-mode, this setting will always cause the flash to fire
for the takePicture API. Otherwise, if the video device does not support this mode, this value is equivalent
to auto .
|
on | The video device's fill light will be turned on (and remain on) until this setting is changed again, or the underlying track object has ended. |
AudioStreamSource
interfaceinterface AudioStreamSource : EventTarget {
readonly attribute unsigned long gain;
void stop ();
static unsigned long getNumDevices ();
};
gain
of type unsigned long, readonlystop
ended
state. Same behavior of the old LocalMediaStream's stop
API, but only for this track source.
void
getNumDevices
, staticgetUserMedia
.
Issue: This information deliberately adds to the fingerprinting surface of the UA. However, this information
can also be obtained by other round-about techniques using getUserMedia
, and is important for determining
whether multiple devices of this type are available.
Issue: The ability to be notified when new devices become available has been dropped from this proposal (it was available in v4 via the DeviceList object).
unsigned long
The PictureStreamSource derived interface is created by the user agent if the camera source providing the VideoStreamSource
supports an optional "high-resolution picture mode" with picture settings that are separate from those of
its basic video source (which is usually considered its preview
mode).
The PictureStreamSource object presents a set of capabilities and controls for taking high-resolution pictures. The unique settings of this object are only applied at the time when the takePicture API is invoked.
PictureStreamSource
interfaceinterface PictureStreamSource : VideoStreamSource
{
readonly attribute unsigned long photoWidth;
readonly attribute unsigned long photoHeight;
void takePicture ();
attribute EventHandler onpicture;
attribute EventHandler onpictureerror;
};
photoWidth
of type unsigned long, readonlyphotoHeight
of type unsigned long, readonlyonpicture
of type EventHandlerThe BlobEvent returns a picture (as a Blob) in a compressed format (for example: PNG/JPEG) rather than a raw ImageData object due to the expected large, uncompressed size of the resulting pictures.
This Event type (BlobEvent) should be the same thing used in the recording proposal.
onpictureerror
of type EventHandlertakePicture
Issue: We could consider providing a hint or setting for the desired picture format?
void
BlobEvent
interface[Constructor(DOMString type, optional BlobEventInit blobInitDict)]
interface BlobEvent : Event {
readonly attribute Blob data;
};
data
of type Blob, readonly<img>
tag.
dictionary BlobEventInit : EventInit {
Blob data;
};
BlobEventInit
Membersdata
of type BlobWhen MediaStreams are transmitted over the network by way of a peer connection, the tracks that are created on the remote side of the MediaStream will have a remote media source attached as the track's source. This source object allows remote-consumers of the MediaStream's tracks to request specific changes to the tracks. These change requests will be serviced by the RTCPeerConnection source object which is streaming the media over the network.
VideoStreamRemoteSource
interfaceinterface VideoStreamRemoteSource : EventTarget {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
readonly attribute float frameRate;
readonly attribute float bitRate;
};
width
of type unsigned long, readonlyheight
of type unsigned long, readonlyframeRate
of type float, readonlybitRate
of type float, readonlyAudioStreamRemoteSource
interfaceinterface AudioStreamRemoteSource : EventTarget {
readonly attribute float bitRate;
};
bitRate
of type float, readonlyThe following settings have been proposed, but are not included in this version to keep the initial set of settings scoped to those that:
Each setting also includes a brief explanatory rationale for why it's not included:
horizontalAspectRatio
- easily calculated based on width/height in the dimension valuesverticalAspectRatio
- see horizontalAspectRatio explanationorientation
- can be easily calculated based on the width/height values and the current rotationaperatureSize
- while more common on digital cameras, not particularly common on webcams (major use-case
for this feature)shutterSpeed
- see aperatureSize explanationdenoise
- may require specification of the algorithm processing or related image processing filter required
to implement.
effects
- sounds like a v2 or independent feature (depending on the effect).faceDetection
- sounds like a v2 feature. Can also be done using post-processing techniques (though
perhaps not as fast...)
antiShake
- sounds like a v2 feature.geoTagging
- this can be independently associated with a recorded picture/video/audio clip using the
Geolocation API. Automatically hooking up Geolocation to Media Capture sounds like an exercise for v2
given the possible complications.
highDynamicRange
- not sure how this can be specified, or if this is just a v2 feature.skintoneEnhancement
- not a particularly common setting.shutterSound
- Can be accomplished by syncing custom audio playback via the <audio>
tag if desired.
By default, there will be no sound issued.
redEyeReduction
- photo-specific setting. (Could be considered if photo-specific settings
are introduced.)
meteringMode
- photo-specific setting. (Could be considered if photo-specific settings
are introduced.)iso
- photo-specific setting. while more common on digital cameras, not particularly common on webcams (major use-case
for this feature)sceneMode
- while more common on digital cameras, not particularly common on webcams (major use-case
for this feature)antiFlicker
- not a particularly common setting.zeroShutterLag
- this seems more like a hope than a setting. I'd rather just have implementations
make the shutter snap as quickly as possible after takePicture, rather than requiring an opt-in/opt-out
for this setting.
The following settings may be included by working group decision:
This proposal simplifies the application of settings over the previous proposal and unifies the setting names with the constraint names and syntax. This unification allows developers to use the same syntax when defining constraints as well as with the settings APIs.
The settings for each track (if available) are all conveniently located on the source
object for the respective track. Each setting
is defined by a readonly attribute (for example the "width" attribute) which serves as a feature-detection for
the given setting, as well as the current value of the setting at any point in time. The constraint name for each
setting are the same as the name of the readonly attribute. For example, "photoWidth" is both the name of the setting
as well as the name of the constraint. All of the constraints defined in this proposal are listed later.
Reading the current settings are as simple as reading the readonly attribute of the same name. Each setting also has
a range of appropriate values (its capabilities), either enumerated values or a range continuum--these are the same ranges/enumerated
values that may be used when expressing constraints for the given setting. Retrieving the capabilities of a given setting
is done via a getRange
API on each source object. Similarly, requesting a change to a setting is done via a
set
API on each source object. Finally, for symmetry a get
method is also defined which reports
the current value of any setting.
As noted in prior proposals, camera/microphone settings must be applied asynchronously to ensure that web applications can remain responsive for all device types that may not respond quickly to setting changes. This is especially true for settings communications over a peer connection.
Browsers provide a media pipeline from sources to sinks. In a browser, sinks are the <img>, <video> and <audio> tags. Traditional sources include streamed content, files and web resources. The media produced by these sources typically does not change over time - these sources can be considered to be static.
The sinks that display these sources to the user (the actual tags themselves) have a variety of controls for manipulating the source content. For
example, an <img> tag scales down a huge source image of 1600x1200 pixels to fit in a rectangle defined with width="400"
and
height="300"
.
The getUserMedia API adds dynamic sources such as microphones and cameras - the characteristics of these sources can change in response to application needs. These sources can be considered to be dynamic in nature. A <video> element that displays media from a dynamic source can either perform scaling or it can feed back information along the media pipeline and have the source produce content more suitable for display.
Note: This sort of feedback loop is obviously just enabling an "optimization", but it's a non-trivial gain. This optimization can save battery, allow for less network congestion, etc...
This proposal assumes that MediaStream
sinks (such as <video>
, <audio>
,
and even RTCPeerConnection
) will continue to have mechanisms to further transform the source stream beyond that
which the settings described in this proposal offer. (The sink transformation options, including those of RTCPeerConnection
are outside the scope of this proposal.)
The act of changing a setting on a stream's source will, by definition, affect all down-level sinks that are using that source. Many sinks may be able
to take these changes in stride, such as the <video>
element or RTCPeerConnection
. Others like the Recorder API may fail
as a result of a source change.
The RTCPeerConnection
is an interesting object because it acts simultaneously as both a sink and a source for over-the-network
streams. As a sink, it has source transformational capabilities (e.g., lowering bit-rates, scaling-up or down resolutions, adjusting frame-rates), and as a
source it may have its own settings changed by a track source that it provides (in this proposal, such sources are the VideoStreamRemoteSource and
AudioStreamRemoteSource objects).
To illustrate how changes to a given source impact various sinks, consider the following example. This example only uses width and height, but the same
principles apply to any of the settings exposed in this proposal. In the first figure a home client has obtained a video source
from its local video camera. The source device's width and height are 800 pixels by 600 pixels, respectively. Three MediaStream
objects on the
home client contain tracks that use this same source. The three media streams are connected to three different sinks, a <video>
element (A),
another <video>
element (B), and a peer connection (C). The peer connection is streaming the source video to an away client. On the away client
there are two media streams with tracks that use the peer connection as a source. These two media streams are connected to two <video>
element
sinks (Y and Z).
Note that in the current state, all of the sinks on the home client must apply a transformation to the original source's dimensions. A is scaling the video up (resulting in loss of quality), B is scaling the video down, and C is also scaling the video up slightly for sending over the network. On the away client, sink Y is scaling the video way down, while sink Z is not applying any scaling.
Using the settings APIs defined in the next section, the home client's video source is changed to a higher resolution (1920 by 1200 pixels).
Note that the source change immediately effects all of the sinks on home client, but does not impact any of the sinks (or sources) on the away client. With the increase in the home client source video's dimensions, sink A no longer has to perform any scaling, while sink B must scale down even further than before. Sink C (the peer connection) must now scale down the video in order to keep the transmission constant to the away client.
While not shown, an equally valid settings change request could be made of the away client video source (the peer connection on the away client's side). This would not only impact sink Y and Z in the same manner as before, but would also cause re-negotiation with the peer connection on the home client in order to alter the transformation that it is applying to the home client's video source. Such a change would not change anything related to sink A or B or the home client's video source.
Note: This proposal does not define a mechanism by which a change to the away client's video source could automatically trigger a change to the home client's video source. Implementations may choose to make such source-to-sink optimizations as long as they only do so within the constraints established by the application, as the next example describes.
It is fairly obvious that changes to a given source will impact sink consumers. However, in some situations changes to a given sink may also be cause for
implementations to adjust the characteristics of a source's stream. This is illustrated in the following figures. In the first figure below, the home
client's video source is sending a video stream sized at 1920 by 1200 pixels. The video source is also unconstrained, such that the exact source dimensions
are flexible as far as the application is concerned. Two MediaStream
objects contain tracks that use this same source, and those
MediaStream
s are connected to two different <video>
element sinks A and B. Sink A has been sized to width="1920"
and
height="1200"
and is displaying the sources video without any transformations. Sink B has been sized smaller and as a result, is scaling the
video down to fit its rectangle of 320 pixels across by 200 pixels down.
When the application changes sink A to a smaller dimension (from 1920 to 1024 pixels wide and from 1200 to 768 pixels tall), the browser's media pipeline may recognize that none of its sinks require the higher source resolution, and needless work is being done both on the part of the source and on sink A. In such a case and without any other constraints forcing the source to continue producing the higher resolution video, the media pipeline may change the source resolution:
In the above figure, the home client's video source resolution was changed to the max(sinkA, sinkB) in order to optimize playback. While not shown above, the same behavior could apply to peer connections and other sinks.
StreamSourceSettings
mix-in interfaceVideoStreamSource
implementsStreamSourceSettings
;
AudioStreamSource
implementsStreamSourceSettings
;
VideoStreamRemoteSource
implementsStreamSourceSettings
;
AudioStreamRemoteSource
implementsStreamSourceSettings
;
[NoInterfaceObject]
interface StreamSourceSettings {
(MediaSettingsRange
or MediaSettingsList
) getRange (DOMString settingName);
any get (DOMString settingName);
void set (MediaTrackConstraint setting, optional boolean isMandatory = false);
};
getRange
Each setting has an appropriate range of values. These may be either value ranges (a continuum of values) or enumerated values but not both. Value ranges include a min and max value, while enumerated values are provided as a list of values. Both types of setting ranges include an "initial" value, which is the value that is expected to be the source device's default value when it is acquired.
MediaSettingsRange objects are returned when a setting is not an enumerated type. This specification will indicate what the range of values must be for each setting. Given that implementations of various hardware may not exactly map to the same range, an implementation should make a reasonable attempt to translate and scale the hardware's setting onto the mapping provided by this specification. If this is not possible due to a hardware setting supporting (for example) fewer levels of granularity, then the implementation should make the device settings min value reflect the min value reported in this specification, and the same for the max value. Then for values in between the min and max, the implementation may round to the nearest supported value and report that value in the setting.
For example, if the setting is fluxCapacitance, and has a specified range from -10 (min) to 10 (max) in this specification, but the implementation's fluxCapacitance hardware setting only supports values of "off" "medium" and "full", then -10 should be mapped to "off", 10 should map to "full", and 0 should map to "medium". A request to change the value to 3 should be rounded down to the closest supported setting (0).
MediaSettingsList objects should order their enumerated values from minimum to maximum where it makes sense, or in the order defined by the enumerated type where applicable.
Setting name | Dictionary return type | Notes |
---|---|---|
width | MediaSettingsRange | The range should span the video source's pre-set width values with min being the smallest width, and max the largest width. The type of the min/max/initial values are unsigned long. |
photoWidth | MediaSettingsRange | The range should span the video source's high-resolution photo-mode pre-set width values with min being the smallest width, and max the largest width. The type of the min/max/initial values are unsigned long. |
height | MediaSettingsRange | The range should span the video source's pre-set height values with min being the smallest width, and max the largest width. The type of the min/max/initial values are unsigned long. |
photoHeight | MediaSettingsRange | The range should span the video source's high-resolution photo-mode pre-set height values with min being the smallest width, and max the largest width. The type of the min/max/initial values are unsigned long. |
frameRate | MediaSettingsRange | The supported range of frame rates on the device. The type of the min/max/initial values are float. |
rotation | MediaSettingsList | The available video rotation options on the source device. The type of the initial/values array is VideoRotationEnum (DOMString). |
mirror | MediaSettingsList | The available video mirror options on the source device. The type of the initial/values array is VideoMirrorEnum (DOMString). |
zoom | MediaSettingsRange | The supported zoom range on the device. The type of the min/max/initial values are float. The initial value is 1. The float value is a scale factor, for example 0.5 is zoomed out by double, while 2.0 is zoomed in by double. Requests should be rounded to the nearest supporting zoom factor by the implementation (when zoom is supported). |
focusMode | MediaSettingsList | The available focus mode options on the source device. The type of the initial/values array is VideoFocusModeEnum (DOMString). |
fillLightMode | MediaSettingsList | The available fill light mode options on the source device. The type of the initial/values array is VideoFillLightModeEnum (DOMString). |
gain | MediaSettingsRange | The supported gain range on the device. The type of the min/max/initial values are unsigned long. The initial value is 50. |
bitRate | MediaSettingsRange | The supported bit rate range on the device. The type of the min/max/initial values are float. |
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
settingName | DOMString | ? | ? | The name of the setting for which the range of expected values should be returned |
(MediaSettingsRange
or MediaSettingsList
)
get
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
settingName | DOMString | ? | ? | The name of the setting for which the current value of that setting should be returned |
any
set
The set
API is the mechanism for asynchronously requesting that the source device change the value
of a given setting. The API mirrors the syntax used for applying constraints. Generally, the set
API
will be used to apply specific values to a setting (such as setting the flashMode
setting to a specific
value), however ranges can also be applied using the same min/max syntax used in constraints (i.e., setting
width
to a range between 800 and 1200 pixels).
The set
API queues requests until the conclusion of the micro-task after which all of the settings requests
will be evaluated according to the constraint algorithm, and requests that can be honored will be applied to the
source device. Any requests specified using the mandatory
parameter that could not be applied must
generate a settingserror event. All other non-mandatory requests that could not be applied do not cause
any notification to be generated.
For all of the given settings that were changed as a result of a sequence of calls to the set
API during a
micro-task, one single settingschanged event will be generated containing the names of the settings that
changed.
Example: To change the video source's dimensions to any aspect ratio where the height
is 768 pixels and the width is at least 300 pixels, would require two calls to set
:
set({ width: { min: 300}}, true);
set({ height: 768}, true);
In each case where the setting/constraint does not take an enumerated value, the implementation should attempt to match the value onto the nearest supported value of the source device unless the mandatory flag is provided. In the case of mandatory requests, if the setting cannot be exactly supported as requested, then the setting must fail and generate a settingserror event. Regarding width/height values--if an implementation is able to scale the source video to match the requested mandatory constraints, this need not cause a settingserror (but the result may be weirdly proportioned video).
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
setting | MediaTrackConstraint | ? | ? | A JavaScript object (dictionary) consisting of a single property which is the setting name to change,
and whose value is either a primitive value (float/DOMString/etc), or another dictionary consisting of a min
and/or max property and associated values. |
false | boolean isMandatory = | ? | ? | A flag indicating whether this settings change request should be considered mandatory. If a value
of true is provided, then should the settings change fail for some reason, a settingserror
event will be raised. Otherwise, only settingschanged event will be dispatched for the settings
that were successfully changed. The default, if this flag is not provided, is false |
void
dictionary MediaSettingsRange {
any max;
any min;
any initial;
};
MediaSettingsRange
Membersmax
of type anyThe type of this value is specific to the setting. Each setting will describe a specific type. That type must be returned for this attribute.
min
of type anyThe type of this value is specific to the setting. Each setting will describe a specific type. That type must be returned for this attribute.
initial
of type anyThe type of this value is specific to the setting. Each setting will describe a specific type. That type must be returned for this attribute.
dictionary MediaSettingsList {
sequence<any> values;
any initial;
};
MediaSettingsList
Membersvalues
of type sequence<any>The type of this value is specific to the setting. Each setting will describe a specific type. That type must be returned for this attribute.
initial
of type anyThe type of this value is specific to the setting. Each setting will describe a specific type. That type must be returned for this attribute.
MediaSettingsEventHandlers
mix-in interfaceAudioStreamSource
implementsMediaSettingsEventHandlers
;
VideoStreamSource
implementsMediaSettingsEventHandlers
;
AudioStreamRemoteSource
implementsMediaSettingsEventHandlers
;
VideoStreamRemoteSource
implementsMediaSettingsEventHandlers
;
[NoInterfaceObject]
interface MediaSettingsEventHandlers {
attribute EventHandler onsettingserror;
attribute EventHandler onsettingschanged;
};
onsettingserror
of type EventHandlerset
API have been made with at least
one such request using the mandatory flag. The MediaSettingsEvent reports the name of the settings that could not be
applied. The "settingschanged" event fires before the "settingserror" event (if any).onsettingschanged
of type EventHandlerMediaSettingsEvent
interface[Constructor(DOMString type, optional MediaSettingsEventInit eventInitDict)]
interface MediaSettingsEvent : Event {
readonly attribute DOMString[] settings;
};
settings
of type array of DOMString, readonlyMediaSettingsEventInit
dictionarydictionary MediaSettingsEventInit : EventInit {
sequence<DOMString> settings;
};
MediaSettingsEventInit
Memberssettings
of type sequence<DOMString>This proposal defines several constraints for use with video and audio devices.
The following constraints are applicable to video devices
dictionary VideoConstraints : MediaTrackConstraintSet {
(unsigned long or MinMaxULongSubConstraint
) width;
(unsigned long or MinMaxULongSubConstraint
) height;
(unsigned long or MinMaxULongSubConstraint
) photoWidth;
(unsigned long or MinMaxULongSubConstraint
) photoHeight;
VideoRotationEnum
rotation;
VideoMirrorEnum
mirror;
(float or MinMaxFloatSubConstraint
) zoom;
VideoFocusModeEnum
focusMode;
VideoFillLightModeEnum
fillLightMode;
(float or MinMaxFloatSubConstraint
) frameRate;
(float or MinMaxFloatSubConstraint
) bitRate;
};
VideoConstraints
Memberswidth
of type unsigned longMinMaxULongSubConstraintheight
of type unsigned longMinMaxULongSubConstraintphotoWidth
of type unsigned longMinMaxULongSubConstraintphotoHeight
of type unsigned longMinMaxULongSubConstraintrotation
of type VideoRotationEnum
mirror
of type VideoMirrorEnum
zoom
of type floatMinMaxFloatSubConstraintfocusMode
of type VideoFocusModeEnum
fillLightMode
of type VideoFillLightModeEnum
frameRate
of type floatMinMaxFloatSubConstraintbitRate
of type floatMinMaxFloatSubConstraintThe following constraints are applicable to audio devices
dictionary AudioConstraints : MediaTrackConstraintSet {
(unsigned long or MinMaxULongSubConstraint
) gain;
};
AudioConstraints
Membersgain
of type unsigned longMinMaxULongSubConstraintMinMaxULongSubConstraint
dictionarydictionary MinMaxULongSubConstraint {
unsigned long max;
unsigned long min;
};
MinMaxULongSubConstraint
Membersmax
of type unsigned longmin
of type unsigned longMinMaxFloatSubConstraint
dictionarydictionary MinMaxFloatSubConstraint {
float max;
float min;
};
MinMaxFloatSubConstraint
Membersmax
of type floatmin
of type floatThe following JavaScript examples demonstrate how the Settings APIs defined in this proposal could be used.
var audioTrack = (AudioStreamSource.getNumDevices() > 0) ? new AudioStreamTrack() : null; if (audioTrack) audioTrack.onstart = mediaStarted; var videoTrack = (VideoStreamSource.getNumDevices() > 0) ? new VideoStreamTrack() : null; if (videoTrack) videoTrack.onstart = mediaStarted; var MS = new MediaStream(); MS.addTrack(audioTrack); MS.addTrack(videoTrack); navigator.getUserMedia(MS); function mediaStarted() { // One of the video/audio devices started. }
function mediaStarted() { // objectURL technique document.querySelector("video").src = URL.createObjectURL(MS, { autoRevoke: true }); // autoRevoke is the default // direct-assign technique document.querySelector("video").srcObject = MS; // Proposed API at this time }
function mediaStarted() { var videoDevice = videoTrack.source; var maxWidth = videoDevice.getRange("width").max; var maxHeight = videoDevice.getRange("height").max; // Check for 1080p+ support if ((maxWidth >= 1920) && (maxHeight >= 1080)) { // See if I need to change the current settings... if ((videoDevice.width < 1920) && (videoDevice.height < 1080)) { videoDevice.set({ width: maxWidth}, true); videoDevice.set({ height: maxHeight}, true); videoDevice.onsettingserror = failureToComply; } } else failureToComply(); } function failureToComply(e) { if (e) console.error("Devices failed to change " + e.settings); // 'width' and/or 'height' else console.error("Device doesn't support at least 1080p"); }
function mediaStarted() { setupRange( videoTrack.source ); } function setupRange(videoDevice) { var zoomCaps = videoDevice.getRange("zoom"); // Check to see if the device supports zooming... if (zoomCaps.min != zoomCaps.max) { // Set HTML5 range control to min/max values of zoom var zoomControl = document.querySelector("input[type=range]"); zoomControl.min = zoomCaps.min; zoomControl.max = zoomCaps.max; zoomControl.value = videoDevice.zoom; zoomControl.onchange = applySettingChanges; } } function applySettingChanges(e) { videoTrack.source.set({ zoom: parseFloat(e.target.value)}, true); }
function mediaStarted() { return new MediaStream( [ videoTrack, audioTrack ]); }
function mediaStarted() { var videoDevice = videoTrack.source; // Check if this device supports a picture mode... if (videoDevice.takePicture) { videoDevice.onpicture = showPicture; // Turn on flash only for the snapshot...if available if (videoDevice.fillLightMode != "notavailable") videoDevice.set({ fillLightMode: "flash"}, true); else console.info("Flash not available"); videoDevice.takePicture(); } } function showPicture(e) { var img = document.querySelector("img"); img.src = URL.createObjectURL(e.data); }
A newly available device occurs whenever an existing device that was being used by another application (with exclusive access) is relinquished and becomes available for this application to use. Of course, plugging-in a new device also causes a device to become available.
This scenario is not currently possible with this proposal.
var totalVideoDevices = VideoStreamSource.getNumDevices(); var videoTracksList = []; for (var i = 0; i < totalVideoDevices; i++) { var mediaStream = new MediaStream( new VideoStreamTrack() ); // Create a video element and add it to the UI var videoTag = document.createElement('video'); videoTag.srcObject = mediaStream; document.body.appendChild(videoTag); // Request to have the track connected to a source device (queue these up in the for-loop) navigator.getUserMedia(mediaStream); }
This section documents the changes from the prior proposal:
getNumDevices
method).getUserMedia
).PictureDeviceTrack
renamed to PictureStreamSource
and dropped the semantics of it being a track; it's
now just a special type of device source that shares settings with its video source through inheritence.PictureEvent
renamed to the more generic (and re-usable) BlobEvent
. (I considered MessageEvent, but
that has too many other unrelated properties, and ProgressEvents didn't have a place to expose the data.)
level
and VideoStreamTrack's facing
values as these
have no corresponding settings to change.gain
to AudioStreamSource; mirror
, photoWidth
, and
photoHeight
to VideoStreamSource; bitRate
to Audio/VideoStreamRemoteSource. Dropped
dimension
.
I'd like to specially thank Anant Narayanan of Mozilla for collaborating on the new settings design, and EKR for his 2c. Also, thanks to Martin Thomson (Microsoft) for his comments and review.