Search code examples
pythontwiliochatbotopenai-whisper

HTTP401 Error in Twilio WhatsApp when retrieving Audio Message


I am trying to access the audio message a user sends over WhatsApp via the Twilio API.

Here's my error:

ERROR:services.audio_processing:HTTP error: 401 Client Error: Unauthorized for url: https://api.twilio.com/2010-04-01/Accounts/ACa6d0fade9bfb1f8bfdd3238b6ca522b1/Messages/MM503f349644b344315426b6cb68e37ea9/Media/ME0bdd87db3d7c7e7fef2e153694b669e1 INFO:twilio.http_client:-- BEGIN Twilio API Request -- INFO:twilio.http_client:POST Request: https://api.twilio.com/2010-04-01/Accounts/ACa6d0fade9bfb1f8bfdd3238b6ca522b1/Messages.json

My code for the function I use to extract the audio is as follows:

import os
import logging
import uuid
import requests
import urllib.request
from config.env_var import *

import openai
from twilio.rest import Client
from pydub import AudioSegment

logger = logging.getLogger(__name__)

# Find your Account SID and Auth Token at twilio.com/console
client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

def process_audio(media_url):
    ogg_file_path = f'{OUTPUT_DIR}/{uuid.uuid1()}.ogg'
    mp3_file_path = f'{OUTPUT_DIR}/{uuid.uuid1()}.mp3'
    
    try:
        # Authenticated request to get the media file
        response = client.request("GET", media_url)
        print("Response status code: ", response.status_code)
        if response.status_code == 200:
            with open(ogg_file_path, 'wb') as file:
                file.write(response.content)
        else:
            raise Exception(f'Failed to download file: {response.status_code}')
        
        # Load the OGG file
        audio_file = AudioSegment.from_ogg(ogg_file_path)
        # Export the file as MP3
        audio_file.export(mp3_file_path, format="mp3")
        
        with open(mp3_file_path, 'rb') as audio_file:
            transcript = openai.Audio.transcribe(
                'whisper-1', audio_file, api_key=OPENAI_API_KEY)
        
        return {
            'status': 1,
            'text': transcript['text']
        }
    except Exception as e:
        logger.error(f'Error at transcript_audio: {e}')
        return {
            'status': 0,
            'text': 'Transcription failed'
        }
    finally:
        for path in [ogg_file_path, mp3_file_path]:
            if os.path.exists(path):
                os.unlink(path)

I suspected the error was due to not using the right credentials, but I checked my Twilio Auth Token and Twilio Account SID and that wasn't it.


Solution

  • Alright, it turns out you need to do 2 things.

    1. You need to top up your account with credit (even if you have credit from the trial left)
    2. You need to use your API Key and API Secret as credentials in the request.

    Here's what I changed:

    import base64
    
    ......
    def process_audio(media_url):
    ......
            credentials = f"{TWILIO_ACCOUNT_SID}:{TWILIO_AUTH_TOKEN}"
            encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')
            headers = {
                'Authorization': f'Basic {encoded_credentials}'
            }
    
            # Unauthenticated request to get the media file
            response = requests.get(media_url, headers=headers, stream=True)
    ......
    

    After that I was able to download the object into my instance successfully.