Skip to content

dynamic-calm/screw

Repository files navigation

Screw

A little project with Go, Next.js, 0Auth2.0, Nginx, SQLite, WebSocket, FFmpeg, Docker,Grafana and Prometheus.

The audio streams to a Go API via WebSocket connections, where FFmpeg processes each stream in real-time. The processed audio is returned through the same connections and buffered client-side, where it's rendered as a waveform.

About screw (Slowed + Reverb)

Note

This is a learning project. Not a production service.

Features

  • Concurrent processing of audio files.
  • Real-time slowed + reverb audio processing using FFmpeg.
  • In memory rate limiting.
  • Middleware.
  • Google OAuth2.0 authentication with PKCE
  • Database sessions.
  • Performance monitoring via Grafana.

Overview

Overview diagram

Demo

Client

screw-demo.mp4

Audio example

Beat made by me in 2020.

Before

beat.mp4

After

beat-processed.mp4

How it works

High level

From the client you can select audio files. For each selected file a new WebSocket connection gets created. The Go API handles them concurrently. And spawns a new FFmpeg process for each. The data flows from the client, through the API, through FFmpeg stdin, and gets sent back from stdout to the WebSocket. In the client the data gets buffered in a Blob. Then a new URL gets created for it. The waveform and playback are enabled by wavesurfer.js.

Audio Processing

Check ffmpeg.go.

  • Adds reverb using ir.wav.
  • Filters frequencies to 40Hz-2.3kHz range.
  • Slows speed to 90% and lowers pitch.

OAuth2.0

The authentication is implemented using Google's OAuth2.0 with PKCE flow, based on Pilcrow's excellent blog posts. This project adapts and expands his Next.js example into Go.

While there's an official Go OAuth2.0 package available, I decided not to use it for this project.

Key components:

  • Custom PKCE code challenge generation.
  • State parameter validation.
  • Session management using SQLite.
  • Token refresh handling.

The auth flow is in api/auth/google.go.

How to run

Note

At one point this project was deployed to AWS with a GitHub Actions pipeline. That's why you'll find HCL code in /terraform and CI/CD workflow in .github/workflows. I'm no longer running it to avoid costs. If you want to deploy this, you'll need to adapt the configuration for your use case. To try it out locally, follow the instructions below.

Prerequisites

  • Docker and Docker Compose.
  • Google OAuth2.0 credentials (optional).

Setup

  1. Clone the repository.

  2. Copy the example env file:

    cp .env.example .env
  3. Configure your OAuth2.0 credentials in .env (optional).

  4. Start the application:

    make dev
  5. Wait until the api container starts:

    api-1         | 2025/01/20 10:29:55 INFO Server is listening port=3000
  6. Navigate to localhost:8080.

Grafana

To setup the dashboard:

  1. Go to localhost:8080/grafana.
  2. Log in with default credentials:
    • Username: admin
    • Password: admin
  3. Create a new password.
  4. Click on the burger menu on the left. Click Connections > Data Sources > + Add new data sources.
  5. Click Prometheus from the list.
  6. Set http://prometheus:9090 in the Connection input.
  7. Click Save & test.
  8. Click on the burger menu again > Dashboards > New > Import.
  9. Copy the contents of the file at the root of the repo named: go-process-grafana-dashboard.json. Click Load. Paste.
  10. Select prometheus as the data source.

You should see this:

Grafana dashboard

Dashboard credits

You can check the original dashboard here.

About

Slowed + Reverb

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published