From fbc8446224e28b6fc8104150723f97bfb42d18ca Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 14:38:01 +0800 Subject: [PATCH 01/10] =?UTF-8?q?refactor:=20=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=B6=88=E9=99=A4=E8=AD=A6=E5=91=8A=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/wwwroot/modules/media.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js index 53944134c3d..c7ca6eed8ec 100644 --- a/src/BootstrapBlazor/wwwroot/modules/media.js +++ b/src/BootstrapBlazor/wwwroot/modules/media.js @@ -25,12 +25,12 @@ export async function open(type, options) { export async function close(selector) { const media = registerBootstrapBlazorModule("MediaDevices"); - let ret = false; + let ret; if (media.stream) { ret = await closeVideoDevice(selector); } else { - ret = await stop(selector); + ret = stop(selector); } return ret; } @@ -205,7 +205,7 @@ export async function record(options) { return ret; } -export async function stop(selector) { +export function stop(selector) { let ret = false; const media = registerBootstrapBlazorModule("MediaDevices"); if (selector) { From 23ebe64c192a7e0e902c4ee05075a634e40843e5 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 14:48:47 +0800 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20GetPreviewDa?= =?UTF-8?q?ta=20=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MediaDevices/DefaultMediaDevices.cs | 12 ++++++++++++ .../MediaDevices/DefaultVideoDevice.cs | 5 +++++ .../Services/MediaDevices/IMediaDevices.cs | 6 ++++++ .../Services/MediaDevices/IVideoDevice.cs | 18 ++++++------------ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs index 37e124abed0..2e4914bb1ea 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs @@ -45,6 +45,18 @@ public async Task Capture() return await module.InvokeAsync("getPreviewUrl"); } + public async Task GetPreviewData() + { + Stream? ret = null; + var module = await LoadModule(); + var stream = await module.InvokeAsync("getPreviewData"); + if (stream != null) + { + ret = await stream.OpenReadStreamAsync(stream.Length); + } + return ret; + } + public async Task Apply(MediaTrackConstraints constraints) { var module = await LoadModule(); diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs index b4af4b6de4a..e68dbae597d 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs @@ -37,6 +37,11 @@ public Task Capture() return deviceService.Capture(); } + public Task GetPreviewData() + { + return deviceService.GetPreviewData(); + } + public Task GetPreviewUrl() { return deviceService.GetPreviewUrl(); diff --git a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs index 8cd7345d6c4..67466fabca4 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs @@ -43,6 +43,12 @@ public interface IMediaDevices /// Task GetPreviewUrl(); + /// + /// Gets the stream of the captured image. + /// + /// + Task GetPreviewData(); + /// /// Apply the media track constraints. /// diff --git a/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs index c197c87bf37..b72bcf73221 100644 --- a/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs +++ b/src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs @@ -36,24 +36,18 @@ public interface IVideoDevice /// Task Capture(); - ///// - ///// Preview a still image from the video stream. - ///// - ///// - //Task Preview(); - - ///// - ///// Gets the stream of the captured image. - ///// - ///// - //Task GetPreviewImage(); - /// /// Gets the preview URL of the captured image. /// /// Task GetPreviewUrl(); + /// + /// Gets the stream of the captured image. + /// + /// + Task GetPreviewData(); + /// /// Apply the media track constraints. /// From 5bd1c34aca681a47084d460a75b6609383422423 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 14:49:51 +0800 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/wwwroot/modules/media.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js index c7ca6eed8ec..1da0959b2a9 100644 --- a/src/BootstrapBlazor/wwwroot/modules/media.js +++ b/src/BootstrapBlazor/wwwroot/modules/media.js @@ -143,11 +143,17 @@ export async function getPreviewUrl() { const capture = new ImageCapture(track); const blob = await capture.takePhoto(); url = URL.createObjectURL(blob); + media.previewBlob = blob; } } return url; } +export async function getPreviewData() { + const media = registerBootstrapBlazorModule("MediaDevices"); + return media.previewBlob; +} + const closeStream = stream => { if (stream) { const tracks = stream.getTracks(); From b2d17e9daa45a4736a416191927abc763af5961d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:02:44 +0800 Subject: [PATCH 04/10] =?UTF-8?q?refactor:=20=E5=A2=9E=E5=8A=A0=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E4=BF=9D=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/wwwroot/modules/media.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js index 1da0959b2a9..6bc9bbfebfd 100644 --- a/src/BootstrapBlazor/wwwroot/modules/media.js +++ b/src/BootstrapBlazor/wwwroot/modules/media.js @@ -6,8 +6,13 @@ export async function enumerateDevices() { console.log("enumerateDevices() not supported."); } else { - await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); - ret = await navigator.mediaDevices.enumerateDevices(); + try { + await navigator.mediaDevices.getUserMedia({ video: true, audio: true }); + ret = await navigator.mediaDevices.enumerateDevices(); + } + catch (e) { + console.warn(e); + } } return ret; } From a01c9c604119c59add118500fd82b8a7d4b198df Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:03:03 +0800 Subject: [PATCH 05/10] =?UTF-8?q?doc:=20=E5=A2=9E=E5=8A=A0=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Samples/VideoDevices.razor | 1 + .../Components/Samples/VideoDevices.razor.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor index 8cf435af1fc..73c72d0bf9b 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor @@ -18,6 +18,7 @@ private IVideoDevice? VideoDeviceService { get; set; } + diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs index 0635c200592..46d1b06ae95 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs @@ -13,6 +13,9 @@ public partial class VideoDevices : IAsyncDisposable [Inject, NotNull] private IVideoDevice? VideoDeviceService { get; set; } + [Inject, NotNull] + private DownloadService? DownloadService { get; set; } + private readonly List _devices = []; private List _items = []; @@ -61,6 +64,15 @@ private async Task OnCapture() _previewUrl = await VideoDeviceService.GetPreviewUrl(); } + private async Task OnDownload() + { + var stream = await VideoDeviceService.GetPreviewData(); + if (stream != null) + { + await DownloadService.DownloadFromStreamAsync("preview.png", stream); + } + } + private async Task OnApply(int width, int height) => await VideoDeviceService.Apply(new MediaTrackConstraints() { Width = width, Height = height }); private async Task DisposeAsync(bool disposing) From 4eebaad50041fd3063840aea71be1fb5757cf870 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:21:06 +0800 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20async=20?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/wwwroot/modules/media.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js index 6bc9bbfebfd..cef7f694731 100644 --- a/src/BootstrapBlazor/wwwroot/modules/media.js +++ b/src/BootstrapBlazor/wwwroot/modules/media.js @@ -154,7 +154,7 @@ export async function getPreviewUrl() { return url; } -export async function getPreviewData() { +export function getPreviewData() { const media = registerBootstrapBlazorModule("MediaDevices"); return media.previewBlob; } From b837080af65137150bf548ade6480f32c156b337 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:26:34 +0800 Subject: [PATCH 07/10] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Services/VideoDeviceTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/UnitTest/Services/VideoDeviceTest.cs b/test/UnitTest/Services/VideoDeviceTest.cs index 500100ea64f..5f270d857c1 100644 --- a/test/UnitTest/Services/VideoDeviceTest.cs +++ b/test/UnitTest/Services/VideoDeviceTest.cs @@ -27,6 +27,7 @@ public async Task GetDevices_Ok() public async Task Open_Ok() { Context.JSInterop.Setup("getPreviewUrl").SetResult("blob:https://test-preview"); + Context.JSInterop.Setup("getPreviewData").SetResult(new MemoryStream([0x01, 0x02])); Context.JSInterop.Setup("open", _ => true).SetResult(true); Context.JSInterop.Setup("close", _ => true).SetResult(true); Context.JSInterop.Setup("apply", _ => true).SetResult(true); @@ -58,5 +59,9 @@ public async Task Open_Ok() await service.Capture(); var url = await service.GetPreviewUrl(); Assert.Equal("blob:https://test-preview", url); + + var data = await service.GetPreviewData(); + Assert.NotNull(data); + Assert.Equal(2, data.Length); } } From 9e01effffbc19ec08da279879f1169c7032c4d50 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:30:08 +0800 Subject: [PATCH 08/10] chore: bump version 9.6.1-beta03 Co-Authored-By: pomeara <8163710+pomeara@users.noreply.github.com> --- src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 1a7f7ef8660..d7b84e4d7b4 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.6.1-beta02 + 9.6.1-beta03 From ee6f85510c54e452340ca3dfac8a7e6fef295214 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:34:49 +0800 Subject: [PATCH 09/10] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Services/VideoDeviceTest.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/UnitTest/Services/VideoDeviceTest.cs b/test/UnitTest/Services/VideoDeviceTest.cs index 5f270d857c1..64e4b616273 100644 --- a/test/UnitTest/Services/VideoDeviceTest.cs +++ b/test/UnitTest/Services/VideoDeviceTest.cs @@ -3,6 +3,9 @@ // See the LICENSE file in the project root for more information. // Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone +using Microsoft.JSInterop; +using UnitTest.Mock; + namespace UnitTest.Services; public class VideoDeviceTest : BootstrapBlazorTestBase @@ -27,7 +30,7 @@ public async Task GetDevices_Ok() public async Task Open_Ok() { Context.JSInterop.Setup("getPreviewUrl").SetResult("blob:https://test-preview"); - Context.JSInterop.Setup("getPreviewData").SetResult(new MemoryStream([0x01, 0x02])); + Context.JSInterop.Setup("getPreviewData").SetResult(new MockJSStreamReference()); Context.JSInterop.Setup("open", _ => true).SetResult(true); Context.JSInterop.Setup("close", _ => true).SetResult(true); Context.JSInterop.Setup("apply", _ => true).SetResult(true); @@ -62,6 +65,6 @@ public async Task Open_Ok() var data = await service.GetPreviewData(); Assert.NotNull(data); - Assert.Equal(2, data.Length); + Assert.Equal(4, data.Length); } } From 171fd44ae8f80cb721627c6a469cc33896c3a747 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Mon, 5 May 2025 15:38:16 +0800 Subject: [PATCH 10/10] =?UTF-8?q?doc:=20=E6=9B=B4=E6=96=B0=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor.Server/Locales/en-US.json | 2 +- src/BootstrapBlazor.Server/Locales/zh-CN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index 22785ecd4e6..d9d406a223e 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -7128,7 +7128,7 @@ "VideoDeviceOpenText": "Open", "VideoDeviceCloseText": "Close", "VideoDeviceCaptureText": "Capture", - "VideoDeviceFlipText": "Flip" + "VideoDeviceDownloadText": "Download" }, "BootstrapBlazor.Server.Components.Samples.AudioDevices": { "AudioDeviceTitle": "IAudioDevice", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 5e3cc128f15..f35f000f138 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -7128,7 +7128,7 @@ "VideoDeviceOpenText": "打开设备", "VideoDeviceCloseText": "关闭设备", "VideoDeviceCaptureText": "截图", - "VideoDeviceFlipText": "翻转镜头" + "VideoDeviceDownloadText": "下载" }, "BootstrapBlazor.Server.Components.Samples.AudioDevices": { "AudioDeviceTitle": "IAudioDevice 音频设备服务",