Search code examples
c#downloadtwiliocontent-typewebrequest

Twilio download recording to file throwing error on JsonConvert.DeserializeObject()


I'm trying to download my recordings on Twilio to a file on my servers local file system (so I can send them to another storage location), but following the code that I've found is throwing an error on the JsonConvert.DeserializeObject() call.

The code that I found is here (called "Retrieve the actual recording media"): https://www.twilio.com/docs/video/api/recordings-resource#filter-by-participant-sid

Here's the code:

static void Main(string[] args)
{
    // Find your Account SID and Auth Token at twilio.com/console
    const string apiKeySid = "SKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    const string apiKeySecret = "your_api_key_secret";

    const string recordingSid = "RTXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    const string uri = $"https://video.twilio.com/v1/Recordings/{recordingSid}/Media";

    var request = (HttpWebRequest)WebRequest.Create(uri);
    request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(apiKeySid + ":" + apiKeySecret)));
    request.AllowAutoRedirect = false;
    string responseBody = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
    var mediaLocation = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseBody)["redirect_to"];

    Console.WriteLine(mediaLocation);
    new WebClient().DownloadFile(mediaLocation, $"{recordingSid}.out");
}

And here's my version:

        var twilioRecordingUri = $"https://api.twilio.com/2010-04-01/Accounts/{recording.AccountSid}/Recordings/{recording.Sid}.mp3?Download=true";

        var request = (HttpWebRequest)WebRequest.Create(new Uri(twilioRecordingUri));
        request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes($"{apiKeySid}:{apiKeySecret}")));
        request.ContentType = "audio/mpeg";
        //request.Accept = "audio/mpeg";
        request.AllowAutoRedirect = false;

        var responseBody = new StreamReader(request.GetResponse().GetResponseStream()).ReadToEnd();
        var deserialized = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseBody);
        var mediaLocation = deserialized["redirect_to"];

        new WebClient().DownloadFile(mediaLocation, $"{recording.Sid}.out");

But executing that code, it fails on the JsonConvert.Deserialize(), like I mentioned; it throws this generic Json error:

Unexpected character encountered while parsing value: �. Path '', line 0, position 0.

Hovering over my "responseBody" variable does show that it's a really long string of funky characters.

My thought was that I should be adding either the "Accept" or "Content-type" to "audio/mpeg" since that's the type of file that I'm trying to retrieve. But when checking Dev Tools at both the request and response headers, neither the Accept or Content-type ever get my audio/mpeg setting that I just specified.

What's wrong with this code here?

Edit: for anyone that noticed the download URL is different from Twilio's example, I found this page that had the updated URL: How do I get a call recording url in twilio when programming in PHP?


Solution

  • It looks like the call you're trying to make is to download an .mp3 file and not a Dictionary<string, string>, so it's likely hitting an error when attempting to deserialize a string into a type that it doesn't match. What you're probably seeing as a result is a Base64 string, especially based on your description. Without seeing at least a sample of the data, I can't know for sure, but I'd guess that you're downloading the raw .mp3 file instead of the file information with location (redirect_to).

    If the result is a pure Base64 string, you should be able to convert it to an array of bytes and write that directly to a file with whatever filename you want. That should get you the mp3 file that you want.