From Local to Live: Deploying an Audio Transcription & Translation App Using Streamlit, Docker, and GitHub Actions

๐ง Introduction
In this blog post, Iโll walk you through how I built, containerized, and deployed a real-time audio transcription and translation app using:
๐ง Streamlit for the frontend
๐ค OpenAI Whisper API for transcription
๐ Translation API for multilingual output
โ๏ธ AWS S3 and EC2 for cloud deployment
๐ณ Docker for containerization
๐ GitHub Actions for CI/CD automation
Whether you're a Python developer, DevOps learner, or looking to automate your deployments โ this article is packed with practical takeaways! ๐
๐ Project Overview
GitHub Repository: S3-Audio-Transcription-Translation-App
This Streamlit app allows users to:
Upload audio files (MP3/WAV)
Transcribe audio using OpenAIโs Whisper
Translate the transcript into multiple languages
Store metadata in MySQL
Upload audio files to AWS S3
๐ ๏ธ Technologies Used
Category | Tools/Services |
Frontend | Streamlit |
Backend | Python, OpenAI API, Translation API |
Storage | AWS S3 |
Database | MySQL |
DevOps | Docker, GitHub Actions, EC2 |
Testing | Pytest |
๐ง Step-by-Step Development
1๏ธโฃ Build the Streamlit App
I used Streamlit to build a clean UI that takes in audio files, triggers transcription, and displays translated text. Here's a snippet:
import streamlit as st
st.title("Audio Transcription & Translation App")
uploaded_file = st.file_uploader("Upload an audio file", type=["mp3", "wav"])
if uploaded_file:
st.audio(uploaded_file)
# Process transcription and translation...
2๏ธโฃ Integrate OpenAI & Translation APIs
Once the file is uploaded, the backend sends it to OpenAIโs Whisper API and returns a transcript. This is then sent to a translation API (e.g., Google Translate or OpenAI GPT) based on user-selected language.
3๏ธโฃ Containerize with Docker
To ensure consistency across development and production, I created a Dockerfile:
# Use a slim Python base image
FROM python:3.9-slim
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
portaudio19-dev \
libasound-dev \
# Add other system dependencies as needed, e.g., libgfortran5 for numpy
--no-install-recommends && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Set the working directory
WORKDIR /app
# Copy the requirements file and install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy the Streamlit application code
COPY . .
# Expose the default Streamlit port
EXPOSE 8501
# Command to run the Streamlit app with environment variables
# The actual environment variables will be passed during `docker run` on EC2
CMD ["streamlit", "run", "appfouthjuly.py", "--server.port=8501", "--server.address=0.0.0.0"]
4๏ธโฃ Automate with GitHub Actions
Every push to main
triggers a GitHub Actions pipeline that:
โ Runs unit tests using
pytest
๐ณ Builds Docker image
๐ค Pushes it to Docker Hub
๐ Deploys it to an EC2 instance via SSH
name: CI/CD Pipeline for Streamlit App to EC2 (Docker Hub)
on:
push:
branches:
- main # or your desired branch
jobs:
build-and-deploy:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx # Add this step to set up Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run Unit Tests
run: |
pytest tests/ --maxfail=1 --disable-warnings --tb=short
- name: Build and push Docker image to Docker Hub
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_PUBLIC_DNS }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
script: |
echo "Pulling latest image..."
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest
echo "Stopping/removing existing container if it exists..."
if [ "$(sudo docker ps -aq -f name=my-streamlit-app)" ]; then
sudo docker stop my-streamlit-app || true
sudo docker rm my-streamlit-app || true
fi
echo "Checking if any other container is publishing port 8501..."
if [ "$(sudo docker ps -q -f publish=8501)" ]; then
CONTAINER_ID_USING_PORT=$(sudo docker ps -q -f publish=8501)
echo "Stopping and removing container $CONTAINER_ID_USING_PORT using port 8501..."
sudo docker stop $CONTAINER_ID_USING_PORT || true
sudo docker rm $CONTAINER_ID_USING_PORT || true
fi
echo "Forcefully killing any process on port 8501 (just in case)..."
sudo fuser -k 8501/tcp || true
echo "Running new container..."
sudo docker run -d \
--network host \
--name my-streamlit-app \
-e MYSQL_HOST="127.0.0.1" \
-e MYSQL_USER="${{ secrets.MYSQL_USERNAME }}" \
-e MYSQL_PASSWORD="${{ secrets.MYSQL_PASSWORD }}" \
-e MYSQL_DATABASE="${{ secrets.MYSQL_DATABASE_NAME }}" \
-e OPENAI_API_KEY="${{ secrets.OPENAI_API_KEY }}" \
-e S3_BUCKET_NAME="${{ secrets.S3_BUCKET_NAME }}" \
-e AWS_ACCESS_KEY_ID="${{ secrets.AWS_ACCESS_KEY_ID }}" \
-e AWS_SECRET_ACCESS_KEY="${{ secrets.AWS_SECRET_ACCESS_KEY }}" \
-e AWS_REGION="${{ secrets.AWS_REGION }}" \
${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest
5๏ธโฃ Deploy to EC2
Using appleboy/ssh-action
, the EC2 server pulls the latest image, removes existing containers (if any), and runs the app on port 8501.
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_PUBLIC_DNS }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
script: |
echo "Pulling latest image..."
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest
echo "Stopping/removing existing container if it exists..."
if [ "$(sudo docker ps -aq -f name=my-streamlit-app)" ]; then
sudo docker stop my-streamlit-app || true
sudo docker rm my-streamlit-app || true
fi
echo "Checking if any other container is publishing port 8501..."
if [ "$(sudo docker ps -q -f publish=8501)" ]; then
CONTAINER_ID_USING_PORT=$(sudo docker ps -q -f publish=8501)
echo "Stopping and removing container $CONTAINER_ID_USING_PORT using port 8501..."
sudo docker stop $CONTAINER_ID_USING_PORT || true
sudo docker rm $CONTAINER_ID_USING_PORT || true
fi
echo "Forcefully killing any process on port 8501 (just in case)..."
sudo fuser -k 8501/tcp || true
๐ Environment Variables
Secrets were handled using GitHub Secrets for:
AWS keys
OpenAI API key
MySQL credentials
S3 bucket info
๐งช Testing with Pytest
Before deploying, pytest
is used to validate core functionality (e.g., upload, API call mocks):
- name: Run Unit Tests
run: |
pytest tests/ --maxfail=1 --disable-warnings --tb=short
โ Final Outcome
The app is fully functional and accessible via browser after deployment. On every push to main
, changes are automatically tested, built, and deployed โ zero manual steps!
๐ก What I Learned
Writing production-ready Streamlit apps
Docker fundamentals and image optimization
CI/CD with GitHub Actions
EC2 and SSH deployment strategies
Managing secrets and environment variables securely
๐ Project Links
๐ธ GitHub Repo: kri-sh27/S3-Audio-Transcription-Translation-App
๐ธ Live App:
http://<your-ec2-public-ip>:8501
๐ Conclusion
This was a rewarding full-stack + DevOps project that touched frontend, backend, cloud, and automation. Iโll continue improving the app by adding:
๐ Real-time microphone support
๐ Logging and monitoring with Prometheus/Grafana
๐ JWT Auth for user access control
Thanks for reading! Feel free to fork the repo, try the app, and connect with me if you have questions or ideas.
๐ฌ Let's Connect!
Subscribe to my newsletter
Read articles from Krishnat Ramchandra Hogale directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Krishnat Ramchandra Hogale
Krishnat Ramchandra Hogale
Hi! Iโm Krishnat, a Senior IT Associate specializing in Performance Engineering at NTT DATA SERVICES. With experience in cloud technologies, DevOps, and automation testing, I focus on optimizing CI/CD pipelines and enhancing infrastructure management. Currently, I'm expanding my expertise in DevOps and AWS Solutions Architecture, aiming to implement robust, scalable solutions that streamline deployment and operational workflows.