Giter Site home page Giter Site logo

w3c / mediacapture-output Goto Github PK

View Code? Open in Web Editor NEW
25.0 35.0 25.0 131 KB

API to manage the rendering of audio on any audio output device

Home Page: https://w3c.github.io/mediacapture-output/

License: Other

CSS 9.11% JavaScript 8.55% HTML 82.34%
webrtc

mediacapture-output's Introduction

Specification 'mediacapture-output'

This is the repository for mediacapture-output. You're welcome to contribute! Let's make the Web rock our socks off!

mediacapture-output's People

Contributors

aboba avatar alvestrand avatar autokagami avatar chrisguttandin avatar dontcallmedom avatar guidou avatar jan-ivar avatar juberti avatar miketaylr avatar plehegar avatar vivienlacourba avatar youennf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mediacapture-output's Issues

Default sinkId value

From TAG review:

Section 2.1 (describing the attribute sinkId should have some prose describing what the value is that is returned (in the default case at a minimum: which I think is the empty string).

Introduce audioDeviceType as an extension to HTMLMediaElement

As we discussed at TPAC, it'd be beneficial to introduce virtual device types so the audio stream can be routed to the default audio end point that maps to the device type. This will give flexibility to apps to choose the audio device type and keep seamless device switching when audio end points (e.g. headphones) are plugged-in or unplugged during run time.

a starting point

partial interface HTMLMediaElement {
    attribute DOMString audioDeviceType;
}

property values

  • "Console": Specifies that the audio output will be sent to the console device.
  • "Multimedia": Specifies that the audio output will be sent to the multimedia device. This should be the default value if the audioDeviceType is not set explicitly.
  • "Communications": Specifies that the audio output will be sent to the communications device. The User Agent is encouraged to use a media playback code path optimized for real-time communications.

remarks

Dynamic change of audioDeviceType during playback is not supported. A new value of audioDeviceType must be set before setting the src or srcObject attribute in order for the value to be effective.

Reserved words for device identifiers don't need 'id-'

...prefix. I believe that the intent of this prefix is to carve out some of the device identifier space for use in this specification. That's unnecessary, though it might make sense to ensure that you only use reserved values that are shorter than the minimum size of an identifier.

As specified, this doesn't avoid the potential for collision. Assuming that an implementation is assigning identifiers while ignorant of this specification, then an implementation might assign one of these identifiers if they use the URL and filename safe variant of base64 to encode identifiers. At 17 characters in length, id-communications is long enough to collide with a 102/104-bit value, which is a plausible amount of entropy, if a mite odd.

Avoid Interface.attributeName notation

E.g. in the sentences

If the HTMLMediaElement.sinkId is no longer present in the list of MediaDeviceInfo.deviceIds returned

This is confusing since sinkId is an instance property, not a static property. E.g. if you type HTMLMediaElement.sinkId in your browser console, the result will be undefined.

Instead say something like "the HTMLMediaElement's sinkId".

Enumeration of output devices and permission model

I have recently gotten an inquiry from a developer attempting to utilize the Audio Devices API to select an output audio device in a situation where there are no input devices (e.g. no microphone or camera).

To enumerate the output devices, they are calling MediaDevices.enumerateDevices to obtain MediaDeviceInfo relating to the devices and then once the user has selected an output device, HTMLMediaElement.setSinkId(deviceId) to set the output device.

Here is the catch. To provide the user with an intelligible list of output devices to select, the label attribute is needed. As noted in Section 9.2.1 of Media Capture and Streams:

 The algorithm described above means that the access to media device information depends on 
 whether or not permission has been granted to the page's origin.

 If no such access has been granted, the MediaDeviceInfo dictionary will contain the deviceId, kind, 
 and groupId.

 If access has been granted for a media device, the MediaDeviceInfo dictionary will contain the 
deviceId, kind, label, and groupId.

So the label attribute can only be obtained if permission has been granted. However, in a situation where there are no input devices, requesting access to the user's (non-existent) microphone and camera is problematic.

Was this interaction intentional?

Point to public-webrtc

Intro currently says comments should be brought to the (to be discontinued) public-media-capture list.

Should setSinkId be functional in SecureContext only?

Following on w3c/webrtc-pc#1945, would it make sense to make setSinkId [SecureContext]? I.e.

console.log("setSinkId" in document.createElement('video')); // false in http

We're looking for guidance on implementing it in Firefox.

Currently, in Chrome this method exists in http, but is pretty much useless (SecurityError).

As to the read-only sinkId attribute, we could leave it ("") or make it SecureContext as well (undefined). With no way to affect the attribute, it serves little purpose.

"For each sinkId whose value is equal to sinkId:"

What collection exactly is being iterated over here? There is no such thing as "For each sinkId".

My best guess is that this is attempting to iterate over all HTMLMediaElements. But which ones? The ones in a document tree? The ones connected to a document? Which documents---all of the documents in the browser? Active documents only?

WG CR review for mediacapture-output

This issue serves to track internal WG review (in the WGs making up the mediacapture TF) of the medacapture-output document for CR publication.
If you have reviewed the document, please add a “thumbs up” reaction to the issue.
If you find issues that you think need addressing before CR publication, please file the issue in Github and mention it in the comments.

The review lasts until Thursday, October 12, 2016. At that time, the chairs will decide whether or not the review result warrants asking the wider community to review the document for CR; if we do ask the wider community, a similar issue wil be filed for tracking that review.

Web Audio design is unlikely

The most likely way that Web Audio will be piped to non-default devices is via a constraints-style object on construction of the AudioContext object-

var audioContext = new AudioContext( { sinkId: requestedSinkId } );

It's highly unlikely we would support output to multiple devices from a single AudioContext simultaneously as a direct case; the resampling and jitter work necessary is kinda goofy from a practical perspective. The output device is the master clock owner, and that becomes more complex in a multiple-output-device-per-Context case. Similarly, changing the single sink live is a bit unstable.

Tracking issues in Web Audio spec: https://github.com/WebAudio/web-audio-api/issues/445, WebAudio/web-audio-api#359.

Why is MediaDeviceId an enum?

No IDL in this spec uses it. Will IDL in other specs?

It seems more likely this should just be a list of strings described in a table, without trying to bring Web IDL into this.

Go back to the default output

As long as the sinkId is not set, the sink is selected by the user agent.
There does not seem to be any way for a web page to go back to this original state.
Should we allow setSinkId('')?

Setting the audio output for a whole context or page

Currently, we are only able to control individual HTMLMediaElement audio output with setSinkId.
We probably need to add something to WebAudio as well.

In most cases, it seems that pages will want to output all their audio to a single device.
Adding such an API to do so would be convenient and would complement setSinkId which would be used to override this default value.

Something at navigator.mediaDevices level might make sense.

Add issues link to the spec

Most W3C specs have a 'participation' section at the top that includes things like the GitHub repo and 'file a bug link' (eg. see UI Events). Please consider adding such a section to this spec.

setSinkId is inconsistent in handling of default value.

sinkId defaults to ""("...the empty string if output is delivered through the user-agent default device")

But [[SinkId]] defaults to null ("Let the element have a [[SinkId]] internal slot, initialized to null.")

This messes up setSinkId in observable ways:

"3. If sinkId is equal to element's [[SinkId]], return a promise resolved with undefined."

await element.setSinkId(element.sinkId); // NotFoundError

Instead, this should succeed, like it does in Chrome.

Use deviceId instead of sinkId

Using deviceId in all the different places would make this consistent with the getUserMedia spec and make it more obvious that these are the same thing that we're talking about.

Behaviour when the system default audio output device changes

What happens when the following happens:

  1. We're playing an HTMLMediaElement through the default device, with a empty sinkId
  2. The default device changes (because the user changes it in the control panel of the operating system, or a new device has been plugged in, and the system sets it as the default).

Is the HTMLMediaElement silently re-routed to the new default device? Does it stop playing ? The former is what happens right now in UAs, the latter is probably not web-compatible.

More broadly, the concept of a "default device" is too overloaded, and needs to be defined. Is it the device that was the default at the time the audio playback started? Is it a kind of "virtual device" that always outputs to whatever the default device is (i.e. the audio output follows the system default, even if the system default changes) ?

Problems with authorization for the output-only case

from Philippe Joseph Cohen:

The issue in the current proposal is that EnumerateDevice returns opaque information before user authorisation as current drafted in the EnumerateDevices specs. So with this opaque information and without the the more meaningful properties (currently the ‘label’ one), apps won’t be in a position to decide if to prompt the user for authorisation to use a specific device based on just the opaque deviceId.

This implies that any authorization prompt must be for all devices (i.e. "web site X wants to enumerate your audio devices", as opposed to "web site X wants to access device Y").

Touching sinkId from background thread

In step 3.5 in Method paragraph of section 2 sinkId appears to be updated from a background thread. Since it is a JavaScript entity I would expect to queue a task in order to update it.

s/SecurityError/NotAllowedError/

When we switched from SecurityError to NotAllowedError two years ago, we forgot this spec.

We should fix that for consistency with getUserMedia.

Also, we should tidy up the terminology by s/authorization/permission/ at the same time.

Default value alias

From TAG review:

Section 4's pre-defined Identifiers adds an alias to the empty string value with "id_multimedia". I wonder for clarity if this should just be the default value.

(probably over taken by events)

CD publication of specification

At the Lisbon TPAC meeting, we will raise the question of whether this spec is ready for publication as CD. Please add to this issue references to the issues that you think have to be resolved before CD publication.

Once all these are resolved, and we think review is adequate, we will ask for CD publication.

Harald, for the chairs.

Controlling 3rd party iframe audio output on a page?

(forgive me, this is my first time attempting to contribute)

We've built an application to allow for video streaming, and we essentially render the video using a browser, then output the framebuffer to another encoding process and send it along to an RTMP destination. (In our case, it's usually FB Live.)

We'd like to enable our users to easily embed other media in their productions.

Today, we capture the audio by changing a machine's default audio device to one we custom wrote, then reroute the audio to our encoder process. This works great generally, but has the major drawback of disabling audio for the rest of the computer.

As the web audio spec has started shipping in Chrome specifically, we've started experimenting with using the web audio output api to redirect the audio properly. Basically, we use the enumerate devices api to find our driver, and if a confluence of things are correct, we direct our audio to go out to that spot explicitly using the setSinkId of audio and video elements.

The issue is if we'd like to embed other external media, like an iframe from YouTube as a simple example, we'd need YouTube to explicitly support switching audio destinations in their postmessage api. We view this as unlikely given our usecase is more edgecase for their business. We think the top-most context for a page should likely be in charge of where audio ends up, if inner iframes haven't changed their sound settings past 'default'. Basically, the top-most context could be in charge of all audio routing ideally.

I'd propose a setSinkId api on an iframe, just like we have on audio / video elements. If this has been done before, I apologize, I wasn't able to find any data on this pretty much anywhere on the web.

I think there's likely some technical challenges here, but I think for advanced audio / video (what i'm obsessed with) it'll help a lot with what the web is great at: linking and embedding resources.

setSinkId does not abort substeps

Per the algorithm given, "If sinkId does not match any audio output device identified by enumerateDevices()," then the promise will be rejected, but then the steps will proceed. You should add "and abort these substeps" to all such cases where you don't want to proceed.

Sample rate can change when an `AudioContext` is running

Requiring the sink ID to be set at construction time simplifies the implementation, since the output sample rate is fixed.

Changing the sample-rate of a device while it is in use is something that can be done on all major desktop operating systems. This sentence implies that this is not the case.

I agree that it's hard to change the sample-rate of an AudioContext, but it's not hard to change it from a device to another, and should be supported.

Of course, in practice and if necessary, UAs will insert a resampler somewhere in the rendering pipeline so that the AudioContext can still render the audio at the original sample-rate, and everything will continue running smoothly.

HTMLMediaElement.setSinkId() when media element is paused doesn't change output device?

http://w3c.github.io/mediacapture-output/#widl-HTMLMediaElement-setSinkId-Promise-void--DOMString-sinkId

The "stop playing this object's audio out of the device represented by the sinkId attribute" and "start playing this object's audio out of the device represented by sinkId" steps are predicated on the media element being playing.

A literal reading of this would be that calling setSinkId() while the media element is paused would have no effect other than changing the sinkId attribute, so that when playback continues it's using the original device.

Making these steps unconditional ought to fix the problem.

"Set the sinkId attribute to sinkId."

sinkId does not have a setter, so this is not possible.

Probably you mean to store the current sinkId in some "internal slot" or "associated sink id", and then set that. Then the getter is defined as returning the value of this HTMLMediaElement's associated sink id.

Headphone connected flag

For certain media player applications, it would be useful to know when headphones are connected (provided the operating system has this information) so that headphone-specific audio can be delivered (e.g. virtual surround). For example, Android has the ACTION_HEADSET_PLUG in the AudioManager class. Could a similar flag be made available within the medacapture-output API? It must be clear that this flag will not always be set, it would depend on the underlying system. But this would be a useful signal and one that many systems, especially mobile, do track.

Could there perhaps be a headset plugged property on each audio device and an event triggered when this status changes? Also an interface to query the current headphone plugged state on a given sinkID?

Predefined IDs conflict with future direction of device selection

I am concerned that the use of predefined IDs with somewhat vague meanings (see https://cdn.rawgit.com/w3c/mediacapture-output/master/index.html#mediadeviceid-enum) sets up a recipe for confusion that will not be easy to get rid of in the future. While these appear to map to some existing MS Windows concepts, that does not provide applications with the ability to offer a meaningful choice of output device to end users (imagine offering users the choice of "playback" or "communications" in a music synthesizer app, for example). I suggest that these IDs be omitted from the spec altogether at this stage.

My belief is that most developers need to be able to discover devices that satisfy various context-dependent constraints, e.g. "is a headphone", "is a speaker", "can support 44K sample rate", "can support a 5.1 channel layout". I am aware that this work is being deferred to a later phase of enhancing enumerateDevices(), and so on. But I think that's the best place to focus effort on selecting devices, rather than on a stopgap distinction between playback and communications.

Checking validity and access of SinkId should be asynchronous

In the algorithm of section 2.2 for setSinkID, the following steps are in the synchronous section:

  1. If the sinkId does not match any audio output device identified by enumerateDevices(), return a promise rejected with a new DOMException whose name is NotFoundError.
  2. If application is not authorized to play audio through the device identified by the given sinkId, return a promise rejected with a new DOMException whose name is SecurityError.

It turns out that checking 2) (which is a prerequisite for 3) requires enumerating the output devices, which can be a slow operation. We suggest that this is better done in the asynchronous section.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.