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);