RemotePlayback
Hand one video or audio element to a TV, a speaker or a cast receiver on the network - and know what happens to it there, including when the user ends the cast from the device itself.
@inject Bit.Butil.RemotePlayback remotePlaybackMDN reference
True when media elements expose a remote object. Chromium and Safari implement it; note that the presence of the API says nothing about whether any device is on the network - that is what WatchAvailability answers.
@inject Bit.Butil.RemotePlayback remotePlayback
var isSupported = await remotePlayback.IsSupported();The callback fires immediately with the current answer and again whenever it changes, so a cast button can be hidden until there is somewhere to cast to. Watching costs battery - the browser keeps scanning the network - so dispose the subscription when the UI it feeds goes away.
var subscription = await remotePlayback.WatchAvailability(mediaElement, available =>
{
showCastButton = available;
StateHasChanged();
});
// later - or when the component is disposed
await subscription!.DisposeAsync();Prompt opens the browser's own device picker and needs a user gesture. A true from it means the picker was answered, not that playback has started - the state subscription is what reports the connection being made, and the disconnect that happens when the user stops the cast from the TV.
await remotePlayback.SubscribeStateChange(mediaElement, state =>
{
// Connecting -> Connected, and Disconnected when the user ends it from the device
Console.WriteLine(state);
});
// from a click handler:
var prompted = await remotePlayback.Prompt(mediaElement);
var state = await remotePlayback.GetState(mediaElement);Sets the element's disableRemotePlayback property, which removes the cast affordance the browser draws inside its own controls. Worth doing for media that must not leave the device - a DRM stream whose licence forbids it, or a local preview.
await remotePlayback.SetDisabled(mediaElement, true); // no cast button on this element
await remotePlayback.SetDisabled(mediaElement, false);API reference
ValueTask<bool> IsSupported()ValueTask<RemotePlaybackState> GetState(ElementReference mediaElement)ValueTask<bool> SetDisabled(ElementReference mediaElement, bool disabled)ValueTask<bool> Prompt(ElementReference mediaElement)ValueTask<ButilSubscription?> WatchAvailability(ElementReference mediaElement, Action<bool> handler)ValueTask<ButilSubscription> SubscribeStateChange(ElementReference mediaElement, Action<RemotePlaybackState> handler)ValueTask DisposeAsync()