diff --git a/Demo/TransformersSharpWebDemo.ApiService/Program.cs b/Demo/TransformersSharpWebDemo.ApiService/Program.cs index 199ccbe..6622066 100644 --- a/Demo/TransformersSharpWebDemo.ApiService/Program.cs +++ b/Demo/TransformersSharpWebDemo.ApiService/Program.cs @@ -1,3 +1,4 @@ +using TransformersSharp.MEAI; using TransformersSharp.Pipelines; using static TransformersSharp.Pipelines.ObjectDetectionPipeline; @@ -23,6 +24,7 @@ } var objectDetectionPipeline = ObjectDetectionPipeline.FromModel("facebook/detr-resnet-50"); +var speechToTextClient = SpeechToTextClient.FromModel("openai/whisper-small"); app.MapPost("/detect", (DetectRequest r) => { @@ -33,6 +35,26 @@ .Produces(StatusCodes.Status200OK) .WithName("Detect"); +app.MapPost("/transcribe", async (HttpRequest request) => +{ + if (!request.HasFormContentType) + return Results.BadRequest("File upload required"); + + var form = await request.ReadFormAsync(); + + string output = string.Empty; + foreach (var file in form.Files) + { + using var stream = file.OpenReadStream(); + output += await speechToTextClient.GetTextAsync(stream); + } + + return Results.Ok(output); + +}).Accepts("multipart/form-data") + .Produces(StatusCodes.Status200OK) + .WithName("Transcribe"); + app.MapDefaultEndpoints(); app.Run(); @@ -40,4 +62,3 @@ record DetectRequest(string Url) { } - diff --git a/Demo/TransformersSharpWebDemo.Web/Components/Layout/NavMenu.razor b/Demo/TransformersSharpWebDemo.Web/Components/Layout/NavMenu.razor index 3088775..0517c48 100644 --- a/Demo/TransformersSharpWebDemo.Web/Components/Layout/NavMenu.razor +++ b/Demo/TransformersSharpWebDemo.Web/Components/Layout/NavMenu.razor @@ -1,6 +1,6 @@  @@ -19,5 +19,11 @@ Object Detection + + diff --git a/Demo/TransformersSharpWebDemo.Web/Components/Pages/ObjectDetection.razor b/Demo/TransformersSharpWebDemo.Web/Components/Pages/ObjectDetection.razor index ba1f1bc..f27c643 100644 --- a/Demo/TransformersSharpWebDemo.Web/Components/Pages/ObjectDetection.razor +++ b/Demo/TransformersSharpWebDemo.Web/Components/Pages/ObjectDetection.razor @@ -3,7 +3,7 @@ @attribute [StreamRendering(true)] @attribute [OutputCache(Duration = 5)] -@inject DetectionApiClient DetectionApi +@inject DemoApiClient DetectionApi Object Detection @@ -14,15 +14,15 @@ .detection { position: absolute; - color: white ; - border: 1px solid black + color: yellow; + border: 5px dotted red; + font-size: 3em; + font-family: "Arial"; }

Object Detection Demo

-

This component demonstrates showing data loaded from a backend API service.

- @if (detectedObjects == null) {

Loading...

@@ -42,9 +42,10 @@ else @code { private DetectResponse? detectedObjects; + private const string url = "https://raw.githubusercontent.com/tonybaloney/TransformersSharp/refs/heads/asr/Demo/assets/dog.jpg"; protected override async Task OnInitializedAsync() { - detectedObjects = await DetectionApi.GetObjectDetectionAsync("https://huggingface.co/datasets/Narsil/image_dummy/raw/main/parrots.png"); + detectedObjects = await DetectionApi.GetObjectDetectionAsync(url); } } diff --git a/Demo/TransformersSharpWebDemo.Web/Components/Pages/Transcribe.razor b/Demo/TransformersSharpWebDemo.Web/Components/Pages/Transcribe.razor new file mode 100644 index 0000000..9a5069c --- /dev/null +++ b/Demo/TransformersSharpWebDemo.Web/Components/Pages/Transcribe.razor @@ -0,0 +1,88 @@ +@page "/transcribe" +@rendermode InteractiveServer +@attribute [StreamRendering(true)] +@attribute [OutputCache(Duration = 5)] + +@inject DemoApiClient demoApi + +Transcribe Audio + +

ASR Demo

+ +

Select a FLAC audio file to transcribe using the backend API service.

+ + + + +@if (isUploading) +{ +

Uploading and transcribing...

+} +@if (!string.IsNullOrEmpty(transcription)) +{ +

Transcription Result:

+

@transcription?.Trim()

+} +@if (!string.IsNullOrEmpty(error)) +{ +

@error

+} + +@code { + private IBrowserFile? selectedFile; + private bool isFileSelected = false; + private bool isUploading = false; + private string? transcription; + private string? error; + + private void OnFileSelected(InputFileChangeEventArgs e) + { + var file = e.File; + if (file.ContentType != "audio/flac"){ + error = "Must be flac"; + selectedFile = null; + isFileSelected = false; + return; + } + + if (file != null) + { + selectedFile = file; + isFileSelected = true; + error = null; + } + else + { + error = "No files selected"; + selectedFile = null; + isFileSelected = false; + } + } + + private async Task UploadFile() + { + if (selectedFile == null) + { + error = "Please select a FLAC file."; + return; + } + + isUploading = true; + transcription = null; + error = null; + + try + { + + transcription = await demoApi.GetTranscribeAsync(selectedFile); + } + catch (Exception ex) + { + error = $"Error: {ex.Message}"; + } + finally + { + isUploading = false; + } + } +} \ No newline at end of file diff --git a/Demo/TransformersSharpWebDemo.Web/DemoApiClient.cs b/Demo/TransformersSharpWebDemo.Web/DemoApiClient.cs new file mode 100644 index 0000000..558f004 --- /dev/null +++ b/Demo/TransformersSharpWebDemo.Web/DemoApiClient.cs @@ -0,0 +1,53 @@ +using Microsoft.AspNetCore.Components.Forms; +using static TransformersSharp.Pipelines.ObjectDetectionPipeline; + +namespace TransformersSharpWebDemo.Web; + +public class DemoApiClient(HttpClient httpClient) +{ + public async Task GetObjectDetectionAsync(string imageUrl, CancellationToken cancellationToken = default) + { + List? detectedObjects = []; + var url = imageUrl; + DetectRequest detectRequest = new(url); // Replace with actual URL + // Extend timeout because this can take a while + httpClient.Timeout = TimeSpan.FromMinutes(5); + var response = await httpClient.PostAsJsonAsync("/detect", detectRequest, cancellationToken); + + foreach (var detectionResult in await response.Content.ReadFromJsonAsync(cancellationToken)) + { + detectedObjects.Add(detectionResult); + } + + return new(url, detectedObjects?.ToArray() ?? []); + } + + public async Task GetTranscribeAsync(IBrowserFile selectedFile) + { + var content = new MultipartFormDataContent(); + var stream = selectedFile.OpenReadStream(); + var fileContent = new StreamContent(stream); + fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("audio/flac"); + content.Add(fileContent, "file", selectedFile.Name); + + // Adjust the API URL as needed for your environment + var response = await httpClient.PostAsync("/transcribe", content); + + if (response.IsSuccessStatusCode) + { + return await response.Content.ReadAsStringAsync(); + } + else + { + throw new Exception($"Transcription failed: {response.ReasonPhrase}"); + } + } +} + +public record DetectRequest(string Url) +{ +} + +public record DetectResponse(string Url, DetectionResult[] DetectionResults) +{ +} diff --git a/Demo/TransformersSharpWebDemo.Web/DetectionApiClient.cs b/Demo/TransformersSharpWebDemo.Web/DetectionApiClient.cs deleted file mode 100644 index c087ee4..0000000 --- a/Demo/TransformersSharpWebDemo.Web/DetectionApiClient.cs +++ /dev/null @@ -1,29 +0,0 @@ -using static TransformersSharp.Pipelines.ObjectDetectionPipeline; - -namespace TransformersSharpWebDemo.Web; - -public class DetectionApiClient(HttpClient httpClient) -{ - public async Task GetObjectDetectionAsync(string imageUrl, CancellationToken cancellationToken = default) - { - List? detectedObjects = []; - var url = imageUrl; - DetectRequest detectRequest = new(url); // Replace with actual URL - var response = await httpClient.PostAsJsonAsync("/detect", detectRequest, cancellationToken); - - foreach (var detectionResult in await response.Content.ReadFromJsonAsync(cancellationToken)) - { - detectedObjects.Add(detectionResult); - } - - return new(url, detectedObjects?.ToArray() ?? []); - } -} - -public record DetectRequest(string Url) -{ -} - -public record DetectResponse(string Url, DetectionResult[] DetectionResults) -{ -} diff --git a/Demo/TransformersSharpWebDemo.Web/Program.cs b/Demo/TransformersSharpWebDemo.Web/Program.cs index dfb11e2..d173ccf 100644 --- a/Demo/TransformersSharpWebDemo.Web/Program.cs +++ b/Demo/TransformersSharpWebDemo.Web/Program.cs @@ -12,7 +12,7 @@ builder.Services.AddOutputCache(); -builder.Services.AddHttpClient(client => +builder.Services.AddHttpClient(client => { // This URL uses "https+http://" to indicate HTTPS is preferred over HTTP. // Learn more about service discovery scheme resolution at https://aka.ms/dotnet/sdschemes. diff --git a/Demo/assets/dog.jpg b/Demo/assets/dog.jpg new file mode 100644 index 0000000..4b56cd0 Binary files /dev/null and b/Demo/assets/dog.jpg differ