The Audio Transcription service provides automatic speech-to-text conversion for audio files, powered by AWS services through a serverless API.
Overview
The transcription system allows you to:
Upload audio files - Support for MP3, WAV, M4A, and OGG formats
Automatic transcription - AWS-powered speech recognition
View results - Real-time access to transcription status and results
Download transcripts - Get completed transcriptions
History - Access previously transcribed files
The service uses AWS Lambda, S3, and Transcribe services through an API Gateway endpoint. Files are uploaded to S3, processed asynchronously, and results are stored for retrieval.
The system accepts the following audio file types:
Maximum file size is 50 MB (51200 KB). Larger files must be compressed or split before upload.
Transcription Workflow
Access transcription interface
Navigate to the transcription section from the main menu
Select audio file
Choose a file from your computer (MP3, WAV, M4A, or OGG)
Upload file
The system:
Generates a pre-signed S3 upload URL
Uploads the file directly to AWS S3
Initiates the transcription job
Monitor progress
Check the status of your transcription:
Processing - AWS is transcribing the audio
Completed - Transcription is ready
Failed - An error occurred
View results
Once complete, view or download the transcribed text
API Configuration
The system connects to an AWS API Gateway endpoint:
// AudioTranscriptionController.php:12-15
public function __construct ()
{
$this -> apiBaseUrl = env ( 'TRANSCRIPTION_API_URL' ,
'https://gvs9j8cd3a.execute-api.us-east-1.amazonaws.com/prod' );
}
Set the TRANSCRIPTION_API_URL in your .env file to configure the API endpoint.
Generating Upload URLs
Before uploading, the system requests a pre-signed URL from AWS:
// AudioTranscriptionController.php:28-75
public function generateUploadUrl ( Request $request )
{
$request -> validate ([
'fileName' => 'required|string' ,
'contentType' => 'required|string'
]);
$url = $this -> apiBaseUrl . '/generate-upload-url' ;
$data = json_encode ([
'fileName' => $request -> fileName ,
'contentType' => $request -> contentType
]);
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_POST , true );
curl_setopt ( $ch , CURLOPT_POSTFIELDS , $data );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json' ,
'Content-Length: ' . strlen ( $data )
]);
curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
$decodedResponse = json_decode ( $response , true );
return response () -> json ( $decodedResponse , $httpCode );
}
SSL verification is disabled for development environments. Enable verification in production by removing CURLOPT_SSL_VERIFYPEER = false.
Uploading Files
Once a pre-signed URL is obtained, upload the file directly to S3:
// AudioTranscriptionController.php:80-125
public function uploadFile ( Request $request )
{
$request -> validate ([
'uploadUrl' => 'required|url' ,
'file' => 'required|file|mimes:mp3,wav,m4a,ogg|max:51200'
]);
$file = $request -> file ( 'file' );
$uploadUrl = $request -> uploadUrl ;
$filePath = $file -> getRealPath ();
$ch = curl_init ( $uploadUrl );
curl_setopt ( $ch , CURLOPT_PUT , true );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_INFILE , fopen ( $filePath , 'r' ));
curl_setopt ( $ch , CURLOPT_INFILESIZE , filesize ( $filePath ));
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: ' . $file -> getMimeType ()
]);
curl_setopt ( $ch , CURLOPT_TIMEOUT , 60 );
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
if ( $httpCode >= 200 && $httpCode < 300 ) {
return response () -> json ([
'success' => true ,
'message' => 'Archivo subido exitosamente'
]);
} else {
throw new \Exception ( "Error al subir el archivo. Código HTTP: $httpCode " );
}
}
The upload uses HTTP PUT directly to the S3 pre-signed URL, ensuring secure and efficient file transfer.
Checking Transcription Results
Query the transcription status and results:
Get All Results
// AudioTranscriptionController.php:130-166
public function getResults ( Request $request )
{
$query = $request -> get ( 'getAll' ) ? [ 'getAll' => 'true' ] : [];
$url = $this -> apiBaseUrl . '/results?' . http_build_query ( $query );
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json'
]);
curl_setopt ( $ch , CURLOPT_TIMEOUT , 30 );
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
$decodedResponse = json_decode ( $response , true );
return response () -> json ( $decodedResponse , $httpCode );
}
Get Specific File Results
Search for transcription results by filename:
// AudioTranscriptionController.php:171-213
public function getResultsByFileName ( Request $request )
{
$request -> validate ([
'fileName' => 'required|string'
]);
$url = $this -> apiBaseUrl . '/results?' . http_build_query ([
'fileName' => $request -> fileName
]);
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json'
]);
curl_setopt ( $ch , CURLOPT_TIMEOUT , 30 );
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
$decodedResponse = json_decode ( $response , true );
return response () -> json ( $decodedResponse , $httpCode );
}
Viewing Transcription History
Access the complete history of transcribed files:
// AudioTranscriptionController.php:219-267
public function getHistorial ( Request $request )
{
$url = $this -> apiBaseUrl . '/results?' . http_build_query ([
'getAll' => 'true'
]);
$ch = curl_init ( $url );
curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
curl_setopt ( $ch , CURLOPT_HTTPHEADER , [
'Content-Type: application/json'
]);
curl_setopt ( $ch , CURLOPT_TIMEOUT , 30 );
$response = curl_exec ( $ch );
$httpCode = curl_getinfo ( $ch , CURLINFO_HTTP_CODE );
curl_close ( $ch );
$decodedResponse = json_decode ( $response , true );
$historial = json_decode ( $response , true );
// Sort by filename
if ( is_array ( $historial )) {
usort ( $historial , function ( $a , $b ) {
$nombreA = $a [ 'nombre_archivo' ] ?? $a [ 'archivo' ] ?? $a [ 'filename' ] ?? '' ;
$nombreB = $b [ 'nombre_archivo' ] ?? $b [ 'archivo' ] ?? $b [ 'filename' ] ?? '' ;
return strcasecmp ( $nombreB , $nombreA );
});
}
return response () -> json ( $historial );
}
The history includes:
File names
Upload timestamps
Transcription status
Completed transcriptions
Error messages (if any)
Routes
The transcription system uses these routes:
Route Method Purpose /transcriptionGET Show transcription interface /generate-upload-urlPOST Get S3 pre-signed URL /upload-filePOST Upload file to S3 /get-resultsGET Get all transcription results /get-results-by-filenameGET Get results for specific file /get-historialGET Get complete transcription history
All routes require authentication via the auth middleware.
Error Handling
The system handles various error scenarios:
cURL Errors
if ( $error ) {
throw new \Exception ( "cURL Error: " . $error );
}
Invalid JSON Responses
$decodedResponse = json_decode ( $response , true );
if ( ! $decodedResponse ) {
throw new \Exception ( "Invalid JSON response: " . $response );
}
HTTP Errors
if ( $httpCode >= 200 && $httpCode < 300 ) {
return response () -> json ([ 'success' => true ]);
} else {
throw new \Exception ( "Error al subir el archivo. Código HTTP: $httpCode " );
}
All errors are logged using Laravel’s logging system:
Log :: error ( 'Error obteniendo resultados: ' . $e -> getMessage ());
return response () -> json ([
'error' => 'Error interno del servidor: ' . $e -> getMessage ()
], 500 );
Frontend Integration
The transcription interface uses AJAX to communicate with the backend:
Select file - User chooses audio file
Request URL - Call /generate-upload-url with filename and content type
Upload file - POST file to pre-signed URL via /upload-file
Poll results - Periodically call /get-results-by-filename to check status
Display transcript - Show completed transcription when ready
AWS Architecture
The backend uses a serverless architecture:
API Gateway REST API endpoint for requests
Lambda Functions Serverless processing logic
S3 Bucket Audio file storage
AWS Transcribe Speech-to-text engine
Best Practices
File preparation - Convert audio to supported formats before upload
File size - Compress large files to stay under 50 MB limit
Audio quality - Better audio quality produces better transcriptions
Check status - Poll periodically but not too frequently (every 5-10 seconds)
Handle errors - Implement retry logic for failed uploads
Timeout handling - Set appropriate timeout values for large files
Progress feedback - Show upload and processing progress to users
Result caching - Cache transcription results to avoid repeated API calls
Troubleshooting
Upload Fails
Verify file format is supported
Check file size is under 50 MB
Ensure internet connection is stable
Verify API endpoint is accessible
Transcription Never Completes
Check AWS service status
Verify audio file is not corrupted
Ensure audio contains speech
Review CloudWatch logs for Lambda errors
Empty Results
Confirm file was successfully uploaded to S3
Check transcription job started correctly
Verify audio format is compatible with AWS Transcribe
Review error logs in the transcription results
Security Considerations
The transcription service:
Uses pre-signed URLs with limited validity
Requires authentication for all operations
Uploads files directly to S3 (not through application server)
Stores results in AWS with access controls
Enable SSL verification in production by removing or setting CURLOPT_SSL_VERIFYPEER = true in all cURL requests.
File Management Manage uploaded audio files
AWS Integration Other AWS-powered features