diff --git a/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor b/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor
index 7462a9f529c..a947fd7d90a 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor
+++ b/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor
@@ -17,6 +17,7 @@ private IAudioDevice? AudioDeviceService { get; set; }
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor.cs
index 11d84ce3788..a5f57b8e344 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/AudioDevices.razor.cs
@@ -13,6 +13,9 @@ public partial class AudioDevices : IAsyncDisposable
[Inject, NotNull]
private IAudioDevice? AudioDeviceService { get; set; }
+ [Inject, NotNull]
+ private DownloadService? DownloadService { get; set; }
+
private readonly List
_devices = [];
private List _items = [];
@@ -21,6 +24,8 @@ public partial class AudioDevices : IAsyncDisposable
private bool _isOpen = false;
+ private bool _isDownload = false;
+
private async Task OnRequestDevice()
{
var devices = await AudioDeviceService.GetDevices();
@@ -49,8 +54,18 @@ private async Task OnOpen()
private async Task OnClose()
{
- _isOpen = false;
await AudioDeviceService.Close(".bb-audio");
+ _isOpen = false;
+ _isDownload = true;
+ }
+
+ private async Task OnDownload()
+ {
+ var stream = await AudioDeviceService.GetData();
+ if (stream != null)
+ {
+ await DownloadService.DownloadFromStreamAsync($"data_{DateTime.Now:HHmmss}.wav", stream);
+ }
}
private async Task DisposeAsync(bool disposing)
diff --git a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs
index 46d1b06ae95..f25c4b56680 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs
+++ b/src/BootstrapBlazor.Server/Components/Samples/VideoDevices.razor.cs
@@ -69,7 +69,7 @@ private async Task OnDownload()
var stream = await VideoDeviceService.GetPreviewData();
if (stream != null)
{
- await DownloadService.DownloadFromStreamAsync("preview.png", stream);
+ await DownloadService.DownloadFromStreamAsync($"preview_{DateTime.Now:HHmmss}.png", stream);
}
}
diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json
index d9d406a223e..a3aed59c1b9 100644
--- a/src/BootstrapBlazor.Server/Locales/en-US.json
+++ b/src/BootstrapBlazor.Server/Locales/en-US.json
@@ -7137,6 +7137,9 @@
"BaseUsageIntro": "Perform different operations by calling different API methods",
"AudioDeviceRequestText": "List",
"AudioDeviceOpenText": "Record",
- "AudioDeviceCloseText": "Stop"
+ "AudioDeviceCloseText": "Stop",
+ "AudioDevicePauseText": "Pause",
+ "AudioDeviceResumeText": "Resume",
+ "AudioDeviceDownloadText": "Download"
}
}
diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json
index f35f000f138..a8881f92588 100644
--- a/src/BootstrapBlazor.Server/Locales/zh-CN.json
+++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json
@@ -7139,6 +7139,7 @@
"AudioDeviceOpenText": "录音",
"AudioDeviceCloseText": "停止",
"AudioDevicePauseText": "暂停",
- "AudioDeviceResumeText": "恢复"
+ "AudioDeviceResumeText": "恢复",
+ "AudioDeviceDownloadText": "下载"
}
}
diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultAudioDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultAudioDevice.cs
index 05708cea6cc..95b0420bfe2 100644
--- a/src/BootstrapBlazor/Services/MediaDevices/DefaultAudioDevice.cs
+++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultAudioDevice.cs
@@ -31,4 +31,9 @@ public Task Close(string? selector)
{
return deviceService.Close(selector);
}
+
+ public Task GetData()
+ {
+ return deviceService.GetAudioData();
+ }
}
diff --git a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs
index 2e4914bb1ea..682c58bc570 100644
--- a/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs
+++ b/src/BootstrapBlazor/Services/MediaDevices/DefaultMediaDevices.cs
@@ -62,4 +62,16 @@ public async Task Apply(MediaTrackConstraints constraints)
var module = await LoadModule();
return await module.InvokeAsync("apply", constraints);
}
+
+ public async Task GetAudioData()
+ {
+ Stream? ret = null;
+ var module = await LoadModule();
+ var stream = await module.InvokeAsync("getAudioData");
+ if (stream != null)
+ {
+ ret = await stream.OpenReadStreamAsync(stream.Length);
+ }
+ return ret;
+ }
}
diff --git a/src/BootstrapBlazor/Services/MediaDevices/IAudioDevice.cs b/src/BootstrapBlazor/Services/MediaDevices/IAudioDevice.cs
index dc8f9f68731..8f4685a1402 100644
--- a/src/BootstrapBlazor/Services/MediaDevices/IAudioDevice.cs
+++ b/src/BootstrapBlazor/Services/MediaDevices/IAudioDevice.cs
@@ -29,4 +29,10 @@ public interface IAudioDevice
///
///
Task Close(string? selector);
+
+ ///
+ /// Gets the stream of the audio.
+ ///
+ ///
+ Task GetData();
}
diff --git a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs
index 67466fabca4..99da23a9a25 100644
--- a/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs
+++ b/src/BootstrapBlazor/Services/MediaDevices/IMediaDevices.cs
@@ -55,4 +55,10 @@ public interface IMediaDevices
///
///
Task Apply(MediaTrackConstraints constraints);
+
+ ///
+ /// Gets the stream of the audio.
+ ///
+ ///
+ Task GetAudioData();
}
diff --git a/src/BootstrapBlazor/wwwroot/modules/media.js b/src/BootstrapBlazor/wwwroot/modules/media.js
index cef7f694731..ef4e514a551 100644
--- a/src/BootstrapBlazor/wwwroot/modules/media.js
+++ b/src/BootstrapBlazor/wwwroot/modules/media.js
@@ -202,6 +202,7 @@ export async function record(options) {
audio.classList.remove("d-none");
audio.classList.remove("hidden");
audio.removeAttribute("hidden");
+ media.audioBlob = blob;
}
}
delete media.audioSelector;
@@ -233,3 +234,8 @@ export function stop(selector) {
}
return ret;
}
+
+export function getAudioData() {
+ const media = registerBootstrapBlazorModule("MediaDevices");
+ return media.audioBlob
+}
diff --git a/test/UnitTest/Services/AudioDeviceTest.cs b/test/UnitTest/Services/AudioDeviceTest.cs
index e1a5136c397..9d07721b5b2 100644
--- a/test/UnitTest/Services/AudioDeviceTest.cs
+++ b/test/UnitTest/Services/AudioDeviceTest.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 AudioDeviceTest : BootstrapBlazorTestBase
@@ -28,6 +31,7 @@ public async Task Open_Ok()
{
Context.JSInterop.Setup("open", _ => true).SetResult(true);
Context.JSInterop.Setup("close", _ => true).SetResult(true);
+ Context.JSInterop.Setup("getAudioData").SetResult(new MockJSStreamReference());
var service = Context.Services.GetRequiredService();
var options = new MediaTrackConstraints()
@@ -40,5 +44,9 @@ public async Task Open_Ok()
var close = await service.Close(".bb-audio");
Assert.True(close);
+
+ var data = await service.GetData();
+ Assert.NotNull(data);
+ Assert.Equal(4, data.Length);
}
}