Skip to content

Commit b7e0afe

Browse files
ArgoZhangpomeara
andauthored
feat(IVideoDevice): add GetPreviewData method (#5965)
* refactor: 代码重构消除警告信息 * feat: 增加 GetPreviewData 方法 * feat: 增加预览数据 * refactor: 增加异常保护 * doc: 增加下载示例 * refactor: 移除 async 关键字 * test: 增加单元测试 * chore: bump version 9.6.1-beta03 Co-Authored-By: pomeara <[email protected]> * test: 更新单元测试 * doc: 更新资源文件 --------- Co-authored-by: pomeara <[email protected]>
1 parent 6a3df54 commit b7e0afe

File tree

11 files changed

+69
-20
lines changed

11 files changed

+69
-20
lines changed

src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ private IVideoDevice? VideoDeviceService { get; set; }</Pre>
1818
<Button Text="@Localizer["VideoDeviceOpenText"]" Icon="fa-solid fa-play" OnClick="OnOpenVideo" IsDisabled="_isOpen || string.IsNullOrEmpty(_deviceId)"></Button>
1919
<Button Text="@Localizer["VideoDeviceCloseText"]" Icon="fa-solid fa-stop" OnClick="OnCloseVideo" IsDisabled="!_isOpen"></Button>
2020
<Button Text="@Localizer["VideoDeviceCaptureText"]" Icon="fa-solid fa-camera" OnClick="OnCapture" IsDisabled="!_isOpen"></Button>
21+
<Button Text="@Localizer["VideoDeviceDownloadText"]" Icon="fa-solid fa-download" OnClick="OnDownload" IsDisabled="!_isOpen"></Button>
2122
<Button Text="QVGA" IsDisabled="!_isOpen" OnClickWithoutRender="() => OnApply(320, 240)"></Button>
2223
<Button Text="VGA" IsDisabled="!_isOpen" OnClickWithoutRender="() => OnApply(640, 480)"></Button>
2324
<Button Text="HD" IsDisabled="!_isOpen" OnClickWithoutRender="() => OnApply(1280, 960)"></Button>

src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public partial class VideoDevices : IAsyncDisposable
1313
[Inject, NotNull]
1414
private IVideoDevice? VideoDeviceService { get; set; }
1515

16+
[Inject, NotNull]
17+
private DownloadService? DownloadService { get; set; }
18+
1619
private readonly List<IMediaDeviceInfo> _devices = [];
1720

1821
private List<SelectedItem> _items = [];
@@ -61,6 +64,15 @@ private async Task OnCapture()
6164
_previewUrl = await VideoDeviceService.GetPreviewUrl();
6265
}
6366

67+
private async Task OnDownload()
68+
{
69+
var stream = await VideoDeviceService.GetPreviewData();
70+
if (stream != null)
71+
{
72+
await DownloadService.DownloadFromStreamAsync("preview.png", stream);
73+
}
74+
}
75+
6476
private async Task OnApply(int width, int height) => await VideoDeviceService.Apply(new MediaTrackConstraints() { Width = width, Height = height });
6577

6678
private async Task DisposeAsync(bool disposing)

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7128,7 +7128,7 @@
71287128
"VideoDeviceOpenText": "Open",
71297129
"VideoDeviceCloseText": "Close",
71307130
"VideoDeviceCaptureText": "Capture",
7131-
"VideoDeviceFlipText": "Flip"
7131+
"VideoDeviceDownloadText": "Download"
71327132
},
71337133
"BootstrapBlazor.Server.Components.Samples.AudioDevices": {
71347134
"AudioDeviceTitle": "IAudioDevice",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7128,7 +7128,7 @@
71287128
"VideoDeviceOpenText": "打开设备",
71297129
"VideoDeviceCloseText": "关闭设备",
71307130
"VideoDeviceCaptureText": "截图",
7131-
"VideoDeviceFlipText": "翻转镜头"
7131+
"VideoDeviceDownloadText": "下载"
71327132
},
71337133
"BootstrapBlazor.Server.Components.Samples.AudioDevices": {
71347134
"AudioDeviceTitle": "IAudioDevice 音频设备服务",

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.6.1-beta02</Version>
4+
<Version>9.6.1-beta03</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ public async Task Capture()
4545
return await module.InvokeAsync<string?>("getPreviewUrl");
4646
}
4747

48+
public async Task<Stream?> GetPreviewData()
49+
{
50+
Stream? ret = null;
51+
var module = await LoadModule();
52+
var stream = await module.InvokeAsync<IJSStreamReference?>("getPreviewData");
53+
if (stream != null)
54+
{
55+
ret = await stream.OpenReadStreamAsync(stream.Length);
56+
}
57+
return ret;
58+
}
59+
4860
public async Task<bool> Apply(MediaTrackConstraints constraints)
4961
{
5062
var module = await LoadModule();

src/BootstrapBlazor/Services/MediaDevices/DefaultVideoDevice.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public Task Capture()
3737
return deviceService.Capture();
3838
}
3939

40+
public Task<Stream?> GetPreviewData()
41+
{
42+
return deviceService.GetPreviewData();
43+
}
44+
4045
public Task<string?> GetPreviewUrl()
4146
{
4247
return deviceService.GetPreviewUrl();

src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ public interface IMediaDevices
4343
/// <returns></returns>
4444
Task<string?> GetPreviewUrl();
4545

46+
/// <summary>
47+
/// Gets the stream of the captured image.
48+
/// </summary>
49+
/// <returns></returns>
50+
Task<Stream?> GetPreviewData();
51+
4652
/// <summary>
4753
/// Apply the media track constraints.
4854
/// </summary>

src/BootstrapBlazor/Services/MediaDevices/IVideoDevice.cs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,18 @@ public interface IVideoDevice
3636
/// <returns></returns>
3737
Task Capture();
3838

39-
///// <summary>
40-
///// Preview a still image from the video stream.
41-
///// </summary>
42-
///// <returns></returns>
43-
//Task Preview();
44-
45-
///// <summary>
46-
///// Gets the stream of the captured image.
47-
///// </summary>
48-
///// <returns></returns>
49-
//Task<Stream?> GetPreviewImage();
50-
5139
/// <summary>
5240
/// Gets the preview URL of the captured image.
5341
/// </summary>
5442
/// <returns></returns>
5543
Task<string?> GetPreviewUrl();
5644

45+
/// <summary>
46+
/// Gets the stream of the captured image.
47+
/// </summary>
48+
/// <returns></returns>
49+
Task<Stream?> GetPreviewData();
50+
5751
/// <summary>
5852
/// Apply the media track constraints.
5953
/// </summary>

src/BootstrapBlazor/wwwroot/modules/media.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ export async function enumerateDevices() {
66
console.log("enumerateDevices() not supported.");
77
}
88
else {
9-
await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
10-
ret = await navigator.mediaDevices.enumerateDevices();
9+
try {
10+
await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
11+
ret = await navigator.mediaDevices.enumerateDevices();
12+
}
13+
catch (e) {
14+
console.warn(e);
15+
}
1116
}
1217
return ret;
1318
}
@@ -25,12 +30,12 @@ export async function open(type, options) {
2530

2631
export async function close(selector) {
2732
const media = registerBootstrapBlazorModule("MediaDevices");
28-
let ret = false;
33+
let ret;
2934
if (media.stream) {
3035
ret = await closeVideoDevice(selector);
3136
}
3237
else {
33-
ret = await stop(selector);
38+
ret = stop(selector);
3439
}
3540
return ret;
3641
}
@@ -143,11 +148,17 @@ export async function getPreviewUrl() {
143148
const capture = new ImageCapture(track);
144149
const blob = await capture.takePhoto();
145150
url = URL.createObjectURL(blob);
151+
media.previewBlob = blob;
146152
}
147153
}
148154
return url;
149155
}
150156

157+
export function getPreviewData() {
158+
const media = registerBootstrapBlazorModule("MediaDevices");
159+
return media.previewBlob;
160+
}
161+
151162
const closeStream = stream => {
152163
if (stream) {
153164
const tracks = stream.getTracks();
@@ -205,7 +216,7 @@ export async function record(options) {
205216
return ret;
206217
}
207218

208-
export async function stop(selector) {
219+
export function stop(selector) {
209220
let ret = false;
210221
const media = registerBootstrapBlazorModule("MediaDevices");
211222
if (selector) {

0 commit comments

Comments
 (0)