diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor index 359a5040826..5b611f33b92 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor @@ -13,10 +13,15 @@ private IBluetooth? BluetoothService { get; set; } Name="Normal">
- - - - +
+ + + + + + + +
diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs index 106cf49e745..11eddbd42f0 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs @@ -61,6 +61,8 @@ private async Task OnCapture() _previewUrl = await VideoDeviceService.GetPreviewUrl(); } + private Task OnApply(int width, int height) => VideoDeviceService.Apply(new MediaTrackConstraints() { Width = width, Height = height }); + private async Task DisposeAsync(bool disposing) { if (disposing) diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.css b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.css index 75a4e73f32a..176c2fc8644 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.css +++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.css @@ -1,14 +1,22 @@ -.bb-video { +.bb-actions { + display: flex; + flex-wrap: wrap; + gap: .5rem .5rem; +} + +.bb-video { min-height: 240px; height: auto; width: auto; - margin-top: 1rem; + margin: 1rem; display: block; } .bb-image { border: 1px solid var(--bs-border-color); border-radius: var(--bs-border-radius); - margin-top: 1rem; + margin: 1rem 1rem 0 1rem; display: block; + width: calc(100% - 2rem); + max-width: 640px; } diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 0e6eb0e364b..1a7f7ef8660 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.6.1-beta01 + 9.6.1-beta02 diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs index 8b9f2c68c77..bd01b7a76c6 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs @@ -44,4 +44,10 @@ public async Task Capture() var module = await LoadModule(); return await module.InvokeAsync("getPreviewUrl"); } + + public async Task Apply(MediaTrackConstraints constraints) + { + var module = await LoadModule(); + return await module.InvokeAsync("apply", constraints); + } } diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs index ebe2a6123ed..cc1a2712592 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs @@ -41,4 +41,9 @@ public Task Capture() { return deviceService.GetPreviewUrl(); } + + public Task Apply(MediaTrackConstraints constraints) + { + return deviceService.Apply(constraints); + } } diff --git a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs index 24140322fbe..5e6ee28618b 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs @@ -41,4 +41,11 @@ public interface IMediaDevices /// /// Task GetPreviewUrl(); + + /// + /// Apply the media track constraints. + /// + /// + /// + Task Apply(MediaTrackConstraints constraints); } diff --git a/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs index d838d97ef95..e4b1916a0f2 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs @@ -53,4 +53,11 @@ public interface IVideoDevice /// /// Task GetPreviewUrl(); + + /// + /// Apply the media track constraints. + /// + /// + /// + Task Apply(MediaTrackConstraints constraints); } diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js index ef82408e9d8..b326799d398 100644 --- a/src/BootstrapBlazor/wwwroot/modules/media.js +++ b/src/BootstrapBlazor/wwwroot/modules/media.js @@ -77,6 +77,41 @@ export async function close(videoSelector) { return ret; } +export async function apply(options) { + let ret = false; + try { + const media = registerBootstrapBlazorModule("MediaDevices"); + const { stream } = media; + if (stream && stream.active) { + const tracks = stream.getVideoTracks(); + if (tracks) { + const track = tracks[0]; + const settings = track.getSettings(); + const { aspectRatio } = settings; + if (options.width) { + settings.width = { + exact: options.width, + }; + settings.height = { + exact: Math.floor(options.width / aspectRatio) + }; + } + if (options.facingMode) { + settings.facingMode = { + ideal: options.facingMode, + } + } + console.log(settings); + await track.applyConstraints(settings); + } + } + } + catch (err) { + console.error("Error apply constraints media devices.", err); + } + return ret; +} + export async function getPreviewUrl() { let url = null; const media = registerBootstrapBlazorModule("MediaDevices"); diff --git a/test/UnitTest/Services/VideoDeviceTest.cs b/test/UnitTest/Services/VideoDeviceTest.cs index 7b19d907d64..267c9c4e1b6 100644 --- a/test/UnitTest/Services/VideoDeviceTest.cs +++ b/test/UnitTest/Services/VideoDeviceTest.cs @@ -28,6 +28,7 @@ public async Task Open_Ok() Context.JSInterop.Setup("getPreviewUrl").SetResult("blob:https://test-preview"); Context.JSInterop.Setup("open", _ => true).SetResult(true); Context.JSInterop.Setup("close", _ => true).SetResult(true); + Context.JSInterop.Setup("apply", _ => true).SetResult(true); var service = Context.Services.GetRequiredService(); var options = new MediaTrackConstraints() @@ -44,6 +45,9 @@ public async Task Open_Ok() var close = await service.Close(".bb-video"); Assert.True(close); + var apply = await service.Apply(new MediaTrackConstraints() { Width = 640, Height = 480, VideoSelector = ".bb-video" }); + Assert.True(apply); + Assert.Equal("test-device-id", options.DeviceId); Assert.Equal("user", options.FacingMode); Assert.Equal(640, options.Height);