Skip to content

Text to Speech using Assembly AI and C#

Become a developer with our complete learning paths
Become a developer with our complete learning paths

Hello and welcome back to a new C# tutorial!.

What is AssemblyAI?

This is going to be a special tutorial, but first, let’s talk about  AssemblyAI!.

AssemblyAI’s is a Speech-to-Text API that is trusted by Fortune 500s, startups, and thousands of developers around the world. It Accurately transcribes audio and video files with a simple API Powered by advanced AI.

https://www.assemblyai.com/

 

Getting our API Key

To access the API we will need to get an API key which we will use to authenticate with AssemblyAI.

Signup here!.

Then copy your API key, we will need it later!.

 

Preparing our Audio File

Alright, we will be transcribing the following audio file.

—place it in the C:\ drive directly (or any path of your choice)

—Create a new Console App project—

Uploading our Audio File to The API

So the way we will tackle this is we will first need to provide a URI for our audio file.

Luckily we can just upload our audio file directly to the API!.

And then we can call the transcribing API and pass it the URI created for us!.

Let’s start by adding a global variable for our API key outside the main.

//api key, we will need it a lot
static string API_Key = "KeyHerePlz";

Then create a new HTTP client object.

—in the main method—

// HttpClient is normally created once, then used for all message sending
HttpClient client = new HttpClient();
//set the base address for the API endpoint
client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
//add the request header which is our api key       paste your API key here
client.DefaultRequestHeaders.Add("authorization", API_Key);

Of course, we need the HTTP namespace

using System.Net.Http;

Then let’s create a method called SendFile which will take our client object and the path of the file we will be uploading!.

Let’s add the threading tasks namespace!.

using System.Threading.Tasks;
private static async Task<string> SendFile(HttpClient client, string filePath)
{
    try
    {
				//create a new HTTP request of type post method, and we will use the upload API 
        //for our endpoint
				HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "upload");
        //then we need to add the request header 
				request.Headers.Add("Transer-Encoding", "chunked");
				//read the file 
        var fileReader = System.IO.File.OpenRead(filePath);
        //read the file as a stream using our file reader object
				var streamContent = new StreamContent(fileReader);
				//set the request content to our data stream
        request.Content = streamContent;
				//send the request
        HttpResponseMessage response = await client.SendAsync(request);
	      //return the response as a string!.
				return await response.Content.ReadAsStringAsync();
    }
    catch (Exception ex)
    {
        System.Console.WriteLine($"Exception: {ex.Message}");
        throw;
    }
}

Now in the main method, let’s call our SendFile method and print the data into the console.

// HttpClient is normally created once, then used for all message sending
HttpClient client = new HttpClient();
//set the base address for the API endpoint
client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
//add the request header which is our api key       paste your API key here
client.DefaultRequestHeaders.Add("authorization", API_Key);
//call the send file method
string jsonResult = SendFile(client, @"C:\\audio rec.M4A").Result;
Console.WriteLine(jsonResult);

and now we can see our URL !.

Passing our URL to the API

Alright now to avoid some bugs and weird behavior let’s first clean our client object and then send another request to the API to transcribe our audio file using the URL we get.

//dispose our client object
client.Dispose();
//reinitialize it
client = new HttpClient();
//set the base address
client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
//add our API key to the request header 
client.DefaultRequestHeaders.Add("authorization", API_Key);

Now we need to add our URL, the issue is, we need to extract the URL alone from the JSON response.

So first let’s add newtonsoft JSON library from NuGet.

And add the json namespace.

using Newtonsoft.Json;

now we need to parse our response into a C# object, since our json response for when we uploaded the file had one variable it should be a very simple class like so.

class UploadItem
{
    public string upload_url { get; set; }
}

Then in the main method let’s create the following json object which contains one variable called audio_url.

var json = new
{

		//deserialize our jsonResult into an upload item and get the URL for the audio
    audio_url = JsonConvert.DeserializeObject<UploadItem>(jsonResult).upload_url
};

Then let’s create an HTTP content that represents our JSON object.

//create a string content from our JSON which we will need for our next request
StringContent payload = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");

Then lets send the request to the transcript endpoint, and give it our string content.

HttpResponseMessage response = await client.PostAsync("<https://api.assemblyai.com/v2/transcript>", payload);
//throw an exception if the request did not go through
**response.EnsureSuccessStatusCode();**

Since we are awaiting an async task we need to set our main method to be async as well.

static async Task Main(string[] args)

And let’s display the response!.

var responseJson = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseJson);

Boom!.

 

We can see a huge response that we can get that contains data about our file and the settings of our transcribing, like the content safety for example to censor sensitive stuff, labeling the speakers if we had a conversation, for example, just reading those settings can give you an idea on how powerful this tool is !.

Sending our Ticket ID to the API

For the sake of this simple tutorial, we are only interested in the ID, which we will need to submit to the API again to get our result since our files might take some time to get transcribed depending on their size.

—Copy the ID—

So now let’s change our app a bit so that we can actually choose between uploading a file and getting the ID or ticket from our API and checking whether our file is ready and display its data.

static async Task Main(string[] args)
{
   Console.WriteLine("Please Select 1. to send the file.");
   Console.WriteLine("Please Select 2. to check if it's ready.");
    if (Console.ReadLine() == "1")
    {

				// HttpClient is normally created once, then used for all message sending
				HttpClient client = new HttpClient();
				//set the base address for the API endpoint
				client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
				//add the request header which is our api key       paste your API key here
				client.DefaultRequestHeaders.Add("authorization", API_Key);
				//call the send file method
				string jsonResult = SendFile(client, @"C:\\audio rec.M4A").Result;
				Console.WriteLine(jsonResult);
	      client.Dispose();
	
				//reinitialize it
				client = new HttpClient();
				//set the base address
				client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
				//add our API key to the request header 
				client.DefaultRequestHeaders.Add("authorization", API_Key);				       
				        var json = new
				{
				
						//deserialize our jsonResult into an upload item and get the URL for the audio
				    audio_url = JsonConvert.DeserializeObject<UploadItem>(jsonResult).upload_url
				};
				
        //create a string content from our JSON which we will need for our next request
				StringContent payload = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
        HttpResponseMessage response = await client.PostAsync("<https://api.assemblyai.com/v2/transcript>", payload);
				//throw an exception if the request did not go through
				**response.EnsureSuccessStatusCode();**
	
        var responseJson = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseJson);
    }
    else
    {
       //check if the file is ready
    }

    Console.ReadKey();
}

 

Viewing the Results

Cool Now let’s handle case number 2, to check if our file is ready!.

first, let’s ask the user for the ticket id they get when they submit the file.

else
{
		//ask the user for the ticket id
		Console.WriteLine("please enter the ID");
    string ticketID = Console.ReadLine();

    
}

now finally let’s call the API and send it the ticket id to see if it’s ready!.

else
{
		//ask the user for the ticket id
    string ticketID = Console.ReadLine();

    using (HttpClient httpClient = new HttpClient())
    {
				//pass the API key
				httpClient.DefaultRequestHeaders.Add("Authorization", API_Key);        //set the header to json
				httpClient.DefaultRequestHeaders.Add("Accepts", "application/json");
				//send a get request to the transcript endpoint and add the ticketId to the url
        HttpResponseMessage response = await httpClient.GetAsync("<https://api.assemblyai.com/v2/transcript/>"+ ticketID);
        //make sure the call went through
				response.EnsureSuccessStatusCode();
				//display the data
        var responseJson = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseJson);
    }
}

And then let’s test it out !.

Run the app and select 1.

Copy the ID.

Run the app again.

and click any button and past the ID.

if our file is not ready we will see the following message.

If we wait a bit, then try again.

You can read my magical words talking about our C# masterclass (which you should get if you didn’t already!).

you can even view a score for each word that represents the confidence of the transcription!.

Outro:

As you saw AssemblyAI is a very powerful tool and the sky is the limit!, make sure to check them out and take a look into their docs, they also offer real-time transcription!. which means no need to submit a file and wait as we did!.

If you have other ideas involving AssemblyAI or any other service please let me know down in the comments and I will be more than happy to teach you about it!, other than that I will see you in the next one!.

Lecture Code!.

using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace AssemblyAI
{
    class Program
    {
        static string API_Key = "KeyHere";
        static async Task Main(string[] args)
        {
            Console.WriteLine("Please Select 1. to send the file.");
            Console.WriteLine("Please Select any other button to check if it's ready.");
           
            if (Console.ReadLine() == "1")
            {

                // HttpClient is normally created once, then used for all message sending
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");
                client.DefaultRequestHeaders.Add("authorization", API_Key);

                string jsonResult = SendFile(client, @"C:\\audio rec.M4A").Result;
                Console.WriteLine(jsonResult);
                client.Dispose();

                client = new HttpClient();
                client.BaseAddress = new Uri("<https://api.assemblyai.com/v2/>");

                client.DefaultRequestHeaders.Add("Authorization", API_Key);

                var json = new
                {
                    audio_url = JsonConvert.DeserializeObject<UploadItem>(jsonResult).upload_url
                };

                StringContent payload = new StringContent(JsonConvert.SerializeObject(json), Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PostAsync("<https://api.assemblyai.com/v2/transcript>", payload);
                response.EnsureSuccessStatusCode();

                var responseJson = await response.Content.ReadAsStringAsync();
                Console.WriteLine(responseJson);
            }
            else
            {
                Console.WriteLine("please enter the ID");
                string ticketID = Console.ReadLine();
                using (HttpClient httpClient = new HttpClient())
                {
                    httpClient.DefaultRequestHeaders.Add("Authorization", API_Key);
                    httpClient.DefaultRequestHeaders.Add("Accepts", "application/json");

                    HttpResponseMessage response = await httpClient.GetAsync("<https://api.assemblyai.com/v2/transcript/>"+ ticketID);
                    response.EnsureSuccessStatusCode();

                    var responseJson = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(responseJson);
                }
            }

            Console.ReadKey();
        }

        private static async Task<string> SendFile(HttpClient client, string filePath)
        {
            try
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "upload");
                request.Headers.Add("Transer-Encoding", "chunked");

                var fileReader = System.IO.File.OpenRead(filePath);
                var streamContent = new StreamContent(fileReader);
                request.Content = streamContent;

                HttpResponseMessage response = await client.SendAsync(request);
                return await response.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                System.Console.WriteLine($"Exception: {ex.Message}");
                throw;
            }
        }
       

    }

    class UploadItem
    {
        public string upload_url { get; set; }
    }
}
Lost in coding? Discover our Learning Paths!
Lost in coding? Discover our Learning Paths!
Enter your email and we will send you the PDF guide:
Enter your email and we will send you the PDF guide