AWS Serverless Transcriber — SRS pack¶
This page assembles sections relevant to a software requirements specification: context and problem through security, quality, and operations.
Contents¶
- Summary
- Context and Problem
- Goals, Requirements, and Constraints
- Role and Responsibilities
- System Model
- Architecture and Integrations
- Security, Quality, and Operations
Summary¶
Status¶
In production
Role¶
System Designer
Stack¶
Python, AWS Lambda, API Gateway, DynamoDB, AWS S3, Terraform, LLM API integration
Project value¶
For the user:
- fast transcription of long audio recordings without uploading to heavy SaaS services;
- controlled access to results via Cognito and presigned URLs;
- minimal ongoing costs through a serverless model.
For the professional profile:
- practical design of an AWS serverless workflow;
- working with async processing, webhooks, polling UI, and job lifecycle;
- applying Infrastructure-as-Code through Terraform;
- choosing solutions based on episodic load and cost constraints (cost-driven architecture).
Context and Problem¶
Context and Background¶
Context and Problem¶
There is an episodic need to transcribe long audio recordings: interviews, work discussions, calls, notes, and research materials. A typical file can run 1.5+ hours and weigh hundreds of megabytes.
Ready-made SaaS services solve the task, but for a personal/limited scenario they provide excessive functionality, opaque pricing, and extra operational overhead: the user manually uploads a file, waits for processing, downloads the result, and stores it separately.
Problem¶
The key architectural problem: transcription is a long asynchronous operation, and audio files are too large for direct transfer through API Gateway/Lambda. Therefore the system must separate upload, processing start, webhook receipt, result storage, and transcript download.
Some recordings may contain private information, so it is important to restrict access to the interface, files, and results. At the same time, sending audio to an external transcription provider remains a deliberate trade-off accepted for cost, quality, and lack of owned GPU infrastructure.
Goals, Requirements, and Constraints¶
Goals and Non-Goals¶
Primary project goals¶
- Implement cost-optimal audio transcription for personal use
Out of scope¶
- Not a publicly accessible open system
- Not a paid or monetizable platform
Business requirements¶
- BR-001. The service is accessible over the internet.
- BR-002. Access is limited to authorized users.
- BR-003. The system supports transcription of long audio.
- BR-004. The system supports speaker diarization.
- BR-005. The user can download the completed transcript.
Functional requirements¶
- FR-001. The user receives a presigned upload URL.
- FR-002. The system creates a transcription job whose current status the user can check without refreshing the page.
- FR-003. The system updates job status as processing progresses.
- FR-004. The UI displays a list of jobs and their current status.
- FR-005. The user receives a presigned URL for the completed transcript.
- FR-006. The webhook handler accepts a callback from the transcription provider.
Constraints¶
- CON-001. Files up to 300 MB.
- CON-002. Recording duration up to 6 hours.
- CON-003. Up to 5 files transcribed concurrently.
- CON-004. 1–3 users.
- CON-005. An on-premises model is not considered.
- CON-006. Ongoing infrastructure costs must be minimal.
Non-functional requirements¶
- NFR-001. Access control.
- NFR-002. Cost efficiency.
- NFR-003. Portability.
- NFR-004. Operability.
- NFR-005. Resilience of async workflow.
Requirements (detailed)¶
- BR-001. Internet accessibility The system must be accessible from any device connected to the internet.
- BR-002. Restricted access The system must provide user authorization and authentication. New user registration is not planned, but user management must be supported.
- BR-003. Speaker diarization The system must support splitting the transcript by speakers.
- BR-004. File formats The system must support the most common voice recorder formats — MP3, AAC.
Rules and constraints (detailed)¶
-
CON-001. Deployment region: for users in Europe, the Caucasus, and Turkey. An AWS region with acceptable availability. Low latency is not a critical requirement because the primary scenario is asynchronous.
-
CON-002. Recording file size — up to 300 MB.
-
CON-003. Single recording duration — up to 6 hours. The system must operate reliably on long recordings.
-
CON-004. Final transcription cost The cost per minute at 40 hours per month must not exceed $0.3/minute including infrastructure costs (reference: https://speech2text.ru/my/rate).
-
CON-005. Mandatory access restriction 1–2 accounts for personal use is sufficient.
-
CON-006. Running an open-source transcription model is not planned Due to lack of hardware at the required level, and the economic impracticality of renting such equipment.
-
CON-007. Solution portability The solution must be easy to deploy and, if needed, tear down when the need for it is temporarily gone.
-
CON-008. Minimal maintenance costs The solution must require minimal resources for maintenance (security updates, etc.).
Role and Responsibilities¶
My Role¶
I acted as the system designer and technical owner of the solution.
My work included:
- translating a personal need into requirements, constraints, and an architectural model;
- choosing a serverless architecture given episodic load and cost constraints;
- designing the asynchronous process: upload -> transcription request -> webhook -> result storage -> download;
- designing the transcription job state model;
- selecting AWS services and responsibility boundaries between Lambda, S3, DynamoDB, API Gateway, Cognito, and the external transcription provider;
- documenting sequence diagrams and ADRs;
- using AI-assisted development tools as an implementation accelerator while keeping manual control over architecture, security boundaries, and deployment decisions.
AI Usage¶
The project was developed with AI assistance.
LLMs were used to accelerate implementation, generate boilerplate code, and iterate quickly. Key decisions remained under manual control:
- requirements interpretation;
- domain modeling;
- architecture decisions;
- data boundaries;
- access model;
- code review;
- debugging;
- deployment decisions;
- technical documentation.
System Model¶
Data Model¶
TranscriptionJob¶
The core entity of the transcription process.
Attributes:
fileIdownerUserIdinputS3KeytranscriptS3KeystatusproviderTranscriptIdcreatedAtupdatedAterrorReasonspeakerModefileSizedurationEstimate
System invariants¶
- a job belongs to one user;
- a download URL is issued only to the job owner;
- a transcript can be downloaded only in
READYstatus; - the webhook must be idempotent;
- a repeated callback from the provider must not create a new transcript;
- a failed job must not block the list of other jobs;
- presigned URLs have a limited lifetime.
DynamoDB — job statuses¶
Each transcription job is stored as a DB record with a lifecycle:
| State Machine | Meaning |
|---|---|
UPLOADING | Presigned URL issued; client upload in progress |
TRANSMITTING | Audio uploaded to S3; submission to service initiated |
PROCESSING | Service is transcribing (transcript_id stored) |
READY | Transcript saved to S3; available for download |
ERROR | AssemblyAI or pipeline failure (reason logged) |
Amazon S3¶
- File bucket: audio uploads and generated transcripts (
Transcript.txt). - Static website bucket: SPA served via CloudFront.
API Contracts¶
API Gateway (authentication)¶
| Method | Path | Purpose |
|---|---|---|
GET | /upload-url | Create record; return Presigned POST URL and fileId |
GET | /jobs | List user's jobs (UI polling) |
GET | /download-url?fileId=... | Verify access; Presigned GET URL for transcript |
POST | /webhook | Transcription provider callback (transcript_id) |
All API Gateway routes require JWT (Amazon Cognito) except /webhook (transcription provider callback).
Amazon Cognito (Hosted UI / PKCE)¶
| Method | Path | Purpose |
|---|---|---|
POST | /oauth2/token | Exchange authorization code for Access & ID tokens |
External transcription provider API¶
| Method | Path | Purpose |
|---|---|---|
POST | /v2/transcript | Submit audio URL + webhook URL; returns transcript_id |
GET | /v2/transcript/{id} | Fetch completed transcription text |
Amazon S3 (direct client access)¶
| Method | Target | Purpose |
|---|---|---|
POST | Presigned POST URL | Direct audio upload (bypasses API Gateway limits) |
GET | Presigned GET URL | Direct transcript download |
Architecture and Integrations¶
Architecture¶
Architectural concept¶
The system is built on an event-driven model.
The static frontend is served via S3/CloudFront. The user authenticates through Cognito Hosted UI and calls API Gateway using the obtained JWT. API Gateway routes requests to Lambda functions.
Large audio files do not pass through API Gateway and Lambda. The backend issues a presigned POST URL, after which the browser uploads the file directly to S3. An S3 ObjectCreated event triggers a handler that creates a temporary URL for the transcription provider and submits a new transcription request. The external provider performs long transcription asynchronously and returns the result via webhook. The final text transcript is saved to S3, and the job status is updated and stored in DynamoDB.
architecture-beta
service dynamo(aws:dynamodb)[AWS DynamoDB]
service lambda(aws:lambda)[AWS Lambda]
service api(aws:api-gateway)[AWS API Gateway]
service static(aws:simple-storage-service)[Static website at Amazon S3]
service storage(aws:simple-storage-service)[File storage at Amazon S3]
service browser(logos:chrome)[Browser]
service cognito(aws:cognito)[AWS Cognito]
service ai(logos:webhooks)[Transcriber API]
service front(aws:cloudfront)[AWS CloudFront]
front:T --> B:static
browser:T --> B:api
browser:L --> R:front
browser:B --> T:cognito
api:R --> L:lambda
api:T <-- B:ai
lambda:T --> R:ai
lambda:R --> L:dynamo
lambda:B --> T:storage
storage:L <-- R:browser Integration flows¶
Sequence diagrams¶
Audio file submission¶
sequenceDiagram
autonumber
actor U as Browser (SPA)
participant API as API Gateway
participant L as AWS Lambda
participant S3 as Amazon S3
participant DB as DynamoDB
U->>API: GET /upload-url (+JWT in Header)
activate API
API->>L: Invoke get_upload_url
deactivate API
activate L
L->>DB: Create record (Status: UPLOADING)
L->>S3: Generate Presigned POST URL
activate S3
S3-->>L: Upload link
deactivate S3
L-->>U: JSON: { uploadUrl, fileId }
deactivate L
Direct upload and asynchronous trigger (event-driven)¶
sequenceDiagram
autonumber
actor U as Browser (SPA)
participant L as AWS Lambda
participant S3 as Amazon S3
participant DB as DynamoDB
participant AI as TranscribeProvider
U->>S3: POST Upload audio file (Bypass API Gateway)
activate S3
S3-->>U: 204 No Content (Success)
deactivate S3
S3-)L: Event: ObjectCreated (Async invoke s3_trigger)
activate L
L->>DB: Update status (TRANSMITTING)
L->>S3: Generate temporary GET Presigned URL for AI
L->>AI: POST /v2/transcript (Audio URL + Webhook URL)
activate AI
alt TranscribeProvider accepts request
AI-->>L: 201 Created (transcript_id)
L->>DB: Status = PROCESSING (save ID)
else API error (e.g. HTTP 400/500)
AI-->>L: 4xx / 5xx Error
deactivate AI
L->>DB: Status = ERROR (Log reason)
end
deactivate L
AI processing and webhook (up to several minutes)¶
sequenceDiagram
autonumber
actor U as Browser (SPA)
participant API as API Gateway
participant L as AWS Lambda
participant S3 as Amazon S3
participant DB as DynamoDB
participant AI as TranscribeProvider
loop Every 15 seconds (Polling)
U->>API: GET /jobs
activate API
API->>L: Invoke get_jobs
deactivate API
activate L
L->>DB: Request user's file list
activate DB
DB-->>L: Data (Status: PROCESSING)
deactivate DB
L-->>U: Update UI
deactivate L
end
Note over AI, DB: TranscribeProvider completes processing
AI->>API: POST /webhook (pass transcript_id)
activate API
API->>L: Invoke webhook_TranscribeProvider
deactivate API
activate L
L->>AI: GET /v2/transcript/{id}
activate AI
AI-->>L: Completed transcription text
deactivate AI
L->>S3: PUT Save text (Transcript.txt)
L->>DB: Update status (READY)
deactivate L
Result retrieval (download)¶
sequenceDiagram
autonumber
actor U as Browser (SPA)
participant API as API Gateway
participant L as AWS Lambda
participant S3 as Amazon S3
participant DB as DynamoDB
U->>API: GET /jobs (Next polling interval)
activate API
API-->>U: Status: READY (Download button active)
deactivate API
U->>API: GET /download-url?fileId=...
activate API
API->>L: Invoke get_download_url
deactivate API
activate L
L->>DB: Verify user access rights to file
L->>S3: Generate Presigned GET URL (with Content-Disposition)
L-->>U: JSON: { downloadUrl }
deactivate L
U->>S3: Direct download of Transcript.txt
activate S3
S3-->>U: Transcription file
deactivate S3 Security, Quality, and Operations¶
Security and access model¶
| Zone | Risk | Control |
|---|---|---|
| Authentication | unauthorized user access | Cognito Hosted UI, JWT validation |
| Authorization | downloading another user's transcript | owner check in DynamoDB before issuing presigned GET URL |
| Upload | uploading an oversized/unsupported file | client-side and backend-side validation, content-type/size constraints |
| S3 access | direct public access to files | private buckets, presigned URLs only |
| Webhook | forged callback | shared secret / provider verification |
| Secrets | provider API key leak | Secrets Manager / encrypted env, no secrets in code |
| Logs | private data in logs | do not log transcript/audio content, only status/error metadata |
| Cost abuse | mass launch of expensive jobs | user limits, quotas, AWS budget alerts |
Access requirements¶
- Access to the service must be restricted.
- User data must be isolated.
Authentication — AWS Cognito¶
- User data isolation: AWS Cognito provides built-in account management, registration, 2FA, brute-force protection, etc. The service integrates seamlessly into the AWS ecosystem.
- Per-file access check on download (
get_download_urlverifies access in DynamoDB before issuing a Presigned URL).
Authentication¶
sequenceDiagram
autonumber
actor U as Browser (SPA)
participant API as API Gateway
participant C as Amazon Cognito
U->>API: API request (no JWT / expired JWT)
activate API
API-->>U: 401 Unauthorized
deactivate API
U->>U: SPA clears local data
U->>C: Redirect to Hosted UI login form
activate C
C->>U: Login form
deactivate C
U->>C: Enter credentials and attempt authentication
activate C
alt Invalid credentials
C-->>U: Return error (Invalid credentials)
else Valid credentials
C-->>U: Return Auth Code (via redirect_uri)
deactivate C
U->>C: POST /oauth2/token (Exchange Code for JWT)
activate C
C-->>U: Access & ID Tokens
deactivate C
end Failure modes¶
| Failure mode | Impact | Detection | Mitigation / recovery |
|---|---|---|---|
| Lambda timeout during synchronous transcription | job does not complete | Lambda logs | async workflow + webhook |
| Provider API error 4xx/5xx | job moves to ERROR | provider logs | save reason, show status to user |
| Webhook not received | task stuck in PROCESSING | UI | retry via a new job |
| Repeated webhook | possible result overwrite | duplicate callback | idempotent write via transcriptId |
| User attempts to download another user's transcript | data leak | access check fails | owner verification before issuing presigned URL |
| Presigned URL expired | user cannot upload/download file | client error | generate a new presigned URL |
| S3 upload not completed | task remains in UPLOADING | stuck UPLOADING status | TTL cleanup / retry upload |
| API key leak | unauthorized spend | AWS quota notifications | key rotation, quota reset, transcription provider budget limit + overdraft disabled |
| Cost growth from mass jobs | unexpected bill | AWS Budgets / CloudWatch | quotas, concurrency limit, transcription provider budget limit + overdraft disabled |
| Transcript saved but status not updated | UI does not show ready result | UI does not show ready result | integrity check / debug job logic |
Sizing and cost estimate¶
Expected workload¶
| Parameter | Value |
|---|---|
| Users | 1–3 |
| Audio per month | up to 40 hours |
| Average file length | 1.5+ hours |
| Maximum file length | 6 hours |
| Maximum file size | 300 MB |
| Concurrent jobs | up to 5 |
Cost drivers¶
| Component | What affects cost |
|---|---|
| Transcription provider | audio minutes/hours |
| S3 | volume of audio and transcript files |
| DynamoDB | number of job/status reads |
| Lambda | number of invocations and handler duration |
| API Gateway | number of API requests |
| CloudFront/S3 static hosting | frontend traffic |
| Secrets Manager | provider API key storage |
| CloudWatch | logs retention |
Cost logic¶
The main cost is not AWS compute but the external transcription provider. AWS Lambda, API Gateway, DynamoDB, and S3 remain secondary cost drivers at the given workload profile. Therefore the architecture is optimized not for high load but for minimal ongoing costs and no idle infrastructure.