diff --git a/.fernignore b/.fernignore
index 403ed2a..e209c63 100644
--- a/.fernignore
+++ b/.fernignore
@@ -3,17 +3,15 @@
README.md
LICENSE.md
src/AssemblyAI/AssemblyAI.csproj
-src/AssemblyAI/AssemblyAIClient.cs
src/AssemblyAI/ClientOptions.cs
+src/AssemblyAI/Constants.cs
+src/AssemblyAI/UserAgent.cs
+src/AssemblyAI/AssemblyAIClient.cs
src/AssemblyAI/DependencyInjectionExtensions.cs
+src/AssemblyAI/Files/FilesCustomClient.cs
+src/AssemblyAI/Transcripts/TranscriptsCustomClient.cs
src/AssemblyAI/Realtime/RealtimeTranscriber.cs
src/AssemblyAI/Realtime/WebSocketClient
-src/AssemblyAI/Constants.cs
-src/AssemblyAI/UserAgent.cs
src/AssemblyAI.Test
Samples
-samples
-
-
-
diff --git a/.gitignore b/.gitignore
index b22978f..497377b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -477,4 +477,4 @@ $RECYCLE.BIN/
*.lnk
.idea
-.runsettings
\ No newline at end of file
+.runsettings
diff --git a/src/AssemblyAI.Test/AssemblyAI.Test.csproj b/src/AssemblyAI.Test/AssemblyAI.Test.csproj
index 9e84e9d..c9b6ab5 100644
--- a/src/AssemblyAI.Test/AssemblyAI.Test.csproj
+++ b/src/AssemblyAI.Test/AssemblyAI.Test.csproj
@@ -23,4 +23,10 @@
+
+
+ PreserveNewest
+
+
+
\ No newline at end of file
diff --git a/src/AssemblyAI.Test/FilesClientTests.cs b/src/AssemblyAI.Test/FilesClientTests.cs
new file mode 100644
index 0000000..2712cdb
--- /dev/null
+++ b/src/AssemblyAI.Test/FilesClientTests.cs
@@ -0,0 +1,49 @@
+using NUnit.Framework;
+
+namespace AssemblyAI.Test;
+
+[TestFixture]
+public class FilesClientTests
+{
+ private string _apiKey;
+
+ [SetUp]
+ public void Setup()
+ {
+ // Retrieve the API key from the .runsettings file
+ _apiKey = TestContext.Parameters.Get("ASSEMBLYAI_API_KEY");
+ if(string.IsNullOrEmpty(_apiKey)) throw new Exception("ASSEMBLYAI_API_KEY .runsetting parameter is not set.");
+ }
+
+ [Test]
+ public async Task Should_Upload_File_Using_FileInfo()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ var fileInfo = new FileInfo(testFilePath);
+
+ var uploadedFile = await client.Files.UploadAsync(fileInfo).ConfigureAwait(false);
+
+ Assert.That(uploadedFile, Is.Not.Null);
+ Assert.That(uploadedFile.UploadUrl, Is.Not.Null);
+ }
+
+ [Test]
+ public async Task Should_Upload_File_Using_Stream()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ await using var fileStream = File.OpenRead(testFilePath);
+
+ var uploadedFile = await client.Files.UploadAsync(fileStream).ConfigureAwait(false);
+
+ Assert.That(uploadedFile, Is.Not.Null);
+ Assert.That(uploadedFile.UploadUrl, Is.Not.Null);
+ }
+}
\ No newline at end of file
diff --git a/src/AssemblyAI.Test/TestData/nbc.mp3 b/src/AssemblyAI.Test/TestData/nbc.mp3
new file mode 100644
index 0000000..50ff56f
Binary files /dev/null and b/src/AssemblyAI.Test/TestData/nbc.mp3 differ
diff --git a/src/AssemblyAI.Test/TranscriptTests.cs b/src/AssemblyAI.Test/TranscriptTests.cs
deleted file mode 100644
index 394c96c..0000000
--- a/src/AssemblyAI.Test/TranscriptTests.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using NUnit.Framework;
-
-namespace AssemblyAI.Test;
-
-[TestFixture]
-public class TranscriptTests
-{
- [Test]
- public async Task TestTranscript()
- {
- var client = new AssemblyAIClient("");
- var transcript = await client.Transcripts.SubmitAsync(new TranscriptParams
- {
- AudioUrl = "https://storage.googleapis.com/aai-docs-samples/nbc.mp3"
- });
- Assert.That(transcript, Is.Not.Null);
- Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Queued));
- }
-}
\ No newline at end of file
diff --git a/src/AssemblyAI.Test/TranscriptsClientTests.cs b/src/AssemblyAI.Test/TranscriptsClientTests.cs
new file mode 100644
index 0000000..ce129e0
--- /dev/null
+++ b/src/AssemblyAI.Test/TranscriptsClientTests.cs
@@ -0,0 +1,149 @@
+using NUnit.Framework;
+
+namespace AssemblyAI.Test;
+
+[TestFixture]
+public class TranscriptsClientTests
+{
+ private string _apiKey;
+
+ [SetUp]
+ public void Setup()
+ {
+ // Retrieve the API key from the .runsettings file
+ _apiKey = TestContext.Parameters.Get("ASSEMBLYAI_API_KEY");
+ if(string.IsNullOrEmpty(_apiKey)) throw new Exception("ASSEMBLYAI_API_KEY .runsettings parameter is not set.");
+ }
+
+ [Test]
+ public async Task Should_Submit_Using_Uri()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ var transcript = await client.Transcripts.SubmitAsync(
+ new Uri("https://storage.googleapis.com/aai-docs-samples/nbc.mp3")
+ ).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Queued));
+ }
+
+ [Test]
+ public async Task Should_Submit_Using_Stream()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ await using var stream = File.OpenRead(testFilePath);
+
+ var transcript = await client.Transcripts.SubmitAsync(stream).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Queued));
+ }
+
+ [Test]
+ public async Task Should_Submit_Using_FileInfo()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ var fileInfo = new FileInfo(testFilePath);
+
+ var transcript = await client.Transcripts.SubmitAsync(fileInfo).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Queued));
+ }
+
+ [Test]
+ public async Task Should_Transcribe_Using_Uri()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ var transcript = await client.Transcripts.TranscribeAsync(
+ new Uri("https://storage.googleapis.com/aai-docs-samples/nbc.mp3")
+ ).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Queued));
+ }
+
+ [Test]
+ public async Task Should_Transcribe_From_FileInfo()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ var fileInfo = new FileInfo(testFilePath);
+
+ var transcript = await client.Transcripts.TranscribeAsync(fileInfo).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Completed));
+ }
+
+ [Test]
+ public async Task Should_Transcribe_Using_Stream()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ await using var stream = File.OpenRead(testFilePath);
+
+ var transcript = await client.Transcripts.TranscribeAsync(stream).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Completed));
+ }
+
+ [Test]
+ public async Task Should_Wait_Until_Ready()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+
+ // Adjust the path to where your test file is located
+ var testFilePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData", "nbc.mp3");
+ await using var stream = File.OpenRead(testFilePath);
+
+ var transcript = await client.Transcripts.SubmitAsync(stream).ConfigureAwait(false);
+ transcript = await client.Transcripts.WaitUntilReady(transcript.Id).ConfigureAwait(false);
+
+ Assert.That(transcript, Is.Not.Null);
+ Assert.That(transcript.Id, Is.Not.Null);
+ Assert.That(transcript.Status, Is.EqualTo(TranscriptStatus.Completed));
+ }
+
+ [Test]
+ public async Task Should_Paginate_Transcripts()
+ {
+ // Assuming there's a method to create a configured RawClient instance
+ var client = new AssemblyAIClient(_apiKey);
+ var transcriptPage = await client.Transcripts.ListAsync().ConfigureAwait(false);
+ Assert.That(transcriptPage, Is.Not.Null);
+ Assert.That(transcriptPage.PageDetails.PrevUrl, Is.Not.Null);
+ Assert.That(transcriptPage.Transcripts, Is.Not.Empty);
+
+ var prevPage = await client.Transcripts.ListAsync(transcriptPage.PageDetails.PrevUrl);
+ Assert.That(transcriptPage, Is.Not.Null);
+ Assert.That(transcriptPage.PageDetails.NextUrl, Is.Not.Null);
+ Assert.That(transcriptPage.Transcripts, Is.Not.Empty);
+ }
+}
\ No newline at end of file
diff --git a/src/AssemblyAI.Test/sample.runsettings b/src/AssemblyAI.Test/sample.runsettings
new file mode 100644
index 0000000..eade2b2
--- /dev/null
+++ b/src/AssemblyAI.Test/sample.runsettings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AssemblyAI/AssemblyAIClient.cs b/src/AssemblyAI/AssemblyAIClient.cs
index 9c73a42..987f2f0 100644
--- a/src/AssemblyAI/AssemblyAIClient.cs
+++ b/src/AssemblyAI/AssemblyAIClient.cs
@@ -1,8 +1,9 @@
+#nullable enable
+
using System.Net.Http;
using AssemblyAI;
using AssemblyAI.Core;
-#nullable enable
namespace AssemblyAI;
@@ -38,14 +39,14 @@ public AssemblyAIClient(ClientOptions clientOptions)
}
Files = new FilesClient(client);
- Transcripts = new TranscriptsClient(client);
+ Transcripts = new ExtendedTranscriptsClient(client, this);
Realtime = new RealtimeClient(client);
Lemur = new LemurClient(client);
}
public FilesClient Files { get; init; }
- public TranscriptsClient Transcripts { get; init; }
+ public ExtendedTranscriptsClient Transcripts { get; init; }
public RealtimeClient Realtime { get; init; }
diff --git a/src/AssemblyAI/Files/FilesClient.cs b/src/AssemblyAI/Files/FilesClient.cs
index 4f51ec5..cb73331 100644
--- a/src/AssemblyAI/Files/FilesClient.cs
+++ b/src/AssemblyAI/Files/FilesClient.cs
@@ -7,7 +7,7 @@
namespace AssemblyAI;
-public class FilesClient
+public partial class FilesClient
{
private RawClient _client;
diff --git a/src/AssemblyAI/Files/FilesCustomClient.cs b/src/AssemblyAI/Files/FilesCustomClient.cs
new file mode 100644
index 0000000..b453d46
--- /dev/null
+++ b/src/AssemblyAI/Files/FilesCustomClient.cs
@@ -0,0 +1,20 @@
+using System.Net.Http;
+using System.Text.Json;
+using AssemblyAI;
+using AssemblyAI.Core;
+
+#nullable enable
+
+namespace AssemblyAI;
+
+public partial class FilesClient
+{
+ ///
+ /// Upload a media file to AssemblyAI's servers.
+ ///
+ public async Task UploadAsync(FileInfo audioFile)
+ {
+ using var audioFileStream = audioFile.OpenRead();
+ return await UploadAsync(audioFileStream).ConfigureAwait(false);
+ }
+}
diff --git a/src/AssemblyAI/Transcripts/ExtendedTranscriptsClient.cs b/src/AssemblyAI/Transcripts/ExtendedTranscriptsClient.cs
new file mode 100644
index 0000000..3649017
--- /dev/null
+++ b/src/AssemblyAI/Transcripts/ExtendedTranscriptsClient.cs
@@ -0,0 +1,134 @@
+#nullable enable
+
+using AssemblyAI.Core;
+
+namespace AssemblyAI;
+
+public class ExtendedTranscriptsClient(RawClient client, AssemblyAIClient assemblyAIClient) : TranscriptsClient(client)
+{
+ public Task SubmitAsync(FileInfo audioFile) => SubmitAsync(audioFile, new TranscriptOptionalParams());
+
+ public async Task SubmitAsync(FileInfo audioFile, TranscriptOptionalParams transcriptParams)
+ {
+ using var audioFileStream = audioFile.OpenRead();
+ return await SubmitAsync(audioFileStream, transcriptParams).ConfigureAwait(false);
+ }
+
+ public Task SubmitAsync(Stream audioFileStream) =>
+ SubmitAsync(audioFileStream, new TranscriptOptionalParams());
+
+ public async Task SubmitAsync(Stream audioFileStream, TranscriptOptionalParams transcriptParams)
+ {
+ var fileUpload = await assemblyAIClient.Files.UploadAsync(audioFileStream).ConfigureAwait(false);
+ return await SubmitAsync(new Uri(fileUpload.UploadUrl), transcriptParams).ConfigureAwait(false);
+ }
+
+ public Task SubmitAsync(Uri audioFileUrl) => SubmitAsync(audioFileUrl, new TranscriptOptionalParams());
+
+ public async Task SubmitAsync(Uri audioFileUrl, TranscriptOptionalParams transcriptParams)
+ {
+ return await SubmitAsync(CreateParams(audioFileUrl, transcriptParams)).ConfigureAwait(false);
+ }
+
+ public Task TranscribeAsync(FileInfo audioFile) =>
+ TranscribeAsync(audioFile, new TranscriptOptionalParams());
+
+ public async Task TranscribeAsync(FileInfo audioFile, TranscriptOptionalParams transcriptParams)
+ {
+ using var audioFileStream = audioFile.OpenRead();
+ return await TranscribeAsync(audioFileStream, transcriptParams).ConfigureAwait(false);
+ }
+
+ public Task TranscribeAsync(Stream audioFileStream) =>
+ TranscribeAsync(audioFileStream, new TranscriptOptionalParams());
+
+ public async Task TranscribeAsync(Stream audioFileStream, TranscriptOptionalParams transcriptParams)
+ {
+ var fileUpload = await assemblyAIClient.Files.UploadAsync(audioFileStream).ConfigureAwait(false);
+ return await TranscribeAsync(new Uri(fileUpload.UploadUrl), transcriptParams).ConfigureAwait(false);
+ }
+
+ public Task TranscribeAsync(Uri audioFileUrl) =>
+ TranscribeAsync(audioFileUrl, new TranscriptOptionalParams());
+
+ public async Task TranscribeAsync(Uri audioFileUrl, TranscriptOptionalParams transcriptParams)
+ {
+ var transcript = await SubmitAsync(CreateParams(audioFileUrl, transcriptParams)).ConfigureAwait(false);
+ transcript = await WaitUntilReady(transcript.Id).ConfigureAwait(false);
+ return transcript;
+ }
+
+ public async Task WaitUntilReady(string id)
+ {
+ var transcript = await GetAsync(id).ConfigureAwait(false);
+ while (transcript.Status != TranscriptStatus.Completed && transcript.Status != TranscriptStatus.Error)
+ {
+ await Task.Delay(1000).ConfigureAwait(false);
+ transcript = await GetAsync(transcript.Id).ConfigureAwait(false);
+ }
+
+ return transcript;
+ }
+
+ private TranscriptParams CreateParams(Uri audioFileUrl, TranscriptOptionalParams transcriptParams)
+ {
+ return new TranscriptParams
+ {
+ AudioUrl = audioFileUrl.ToString()
+ // TODO: map other parameters
+ };
+ }
+
+ public Task ListAsync() => ListAsync(new ListTranscriptParams());
+
+ ///
+ /// Retrieve a list of transcripts you created.
+ /// Transcripts are sorted from newest to oldest. The previous URL always points to a page with older transcripts.
+ ///
+ public async Task ListAsync(string listUrl)
+ {
+ // this would be easier to just call the given URL,
+ // but the raw client doesn't let us make requests to full URL
+ // so we'll parse the querystring and pass it to `ListAsync`.
+
+ var queryString = listUrl.Substring(listUrl.IndexOf('?') + 1)
+ .Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(k => k.Split('='))
+ .Where(k => k.Length == 2)
+ .ToLookup(a => a[0], a => Uri.UnescapeDataString(a[1])
+ , StringComparer.OrdinalIgnoreCase);
+ var listTranscriptParams = new ListTranscriptParams();
+ if (queryString.Contains("limit"))
+ {
+ listTranscriptParams.Limit = int.Parse(queryString["limit"].First());
+ }
+
+ if (queryString.Contains("status"))
+ {
+ listTranscriptParams.Status =
+ (TranscriptStatus)Enum.Parse(typeof(TranscriptStatus), queryString["limit"].First());
+ }
+
+ if (queryString.Contains("created_on"))
+ {
+ listTranscriptParams.CreatedOn = queryString["created_on"].First();
+ }
+
+ if (queryString.Contains("before_id"))
+ {
+ listTranscriptParams.BeforeId = queryString["before_id"].First();
+ }
+
+ if (queryString.Contains("after_id"))
+ {
+ listTranscriptParams.AfterId = queryString["after_id"].First();
+ }
+
+ if (queryString.Contains("throttled_only"))
+ {
+ listTranscriptParams.ThrottledOnly = bool.Parse(queryString["throttled_only"].First());
+ }
+
+ return await ListAsync(listTranscriptParams).ConfigureAwait(false);
+ }
+}
\ No newline at end of file
diff --git a/src/AssemblyAI/Transcripts/Requests/ListTranscriptParams.cs b/src/AssemblyAI/Transcripts/Requests/ListTranscriptParams.cs
index 96f2511..e73946c 100644
--- a/src/AssemblyAI/Transcripts/Requests/ListTranscriptParams.cs
+++ b/src/AssemblyAI/Transcripts/Requests/ListTranscriptParams.cs
@@ -9,30 +9,30 @@ public record ListTranscriptParams
///
/// Maximum amount of transcripts to retrieve
///
- public int? Limit { get; init; }
+ public int? Limit { get; set; }
///
/// Filter by transcript status
///
- public TranscriptStatus? Status { get; init; }
+ public TranscriptStatus? Status { get; set; }
///
/// Only get transcripts created on this date
///
- public string? CreatedOn { get; init; }
+ public string? CreatedOn { get; set; }
///
/// Get transcripts that were created before this transcript ID
///
- public string? BeforeId { get; init; }
+ public string? BeforeId { get; set; }
///
/// Get transcripts that were created after this transcript ID
///
- public string? AfterId { get; init; }
+ public string? AfterId { get; set; }
///
/// Only get throttled transcripts, overrides the status filter
///
- public bool? ThrottledOnly { get; init; }
+ public bool? ThrottledOnly { get; set; }
}