Skip to content

existential-birds/behind_the_weather

Repository files navigation

Behind the Weather

I was reading about the Shipping Forecast and it reminded me of how fascinated I was by the weather information numbers that used to exist when I was a kid. I decided to make one myself, with a twist. -ka

Phone-based weather report service narrated in the style of VH1's "Behind the Music." Dial in, enter your zip code, and hear a dramatic forecast delivered like the greatest story ever told.

How It Works

  1. You dial the Twilio phone number
  2. You enter your 5-digit zip code on the keypad
  3. The app looks up your location, fetches the forecast from the National Weather Service, generates a dramatic narrator script, and converts it to speech
  4. You hear your weather report

Setup

Prerequisites

  • Elixir 1.15+
  • Erlang/OTP 26+

Install and run

mix setup
mix phx.server

The server starts at localhost:4000. You'll need the environment variables configured for full functionality.

Environment variables

Set these before running in development or production:

Variable Description
OPENROUTER_API_KEY Script generation via OpenRouter
TWILIO_ACCOUNT_SID Twilio account SID for phone integration
TWILIO_AUTH_TOKEN Twilio auth token for phone integration

Configure one of the following voice providers:

ElevenLabs:

Variable Description
ELEVENLABS_API_KEY API key
ELEVENLABS_VOICE_ID Voice ID for the narrator

Fish Audio:

Variable Description
FISH_AUDIO_API_KEY API key
FISH_AUDIO_MODEL_ID Model ID
FISH_AUDIO_REFERENCE_ID Reference ID for voice cloning

Local call testing

  1. Start an ngrok tunnel to your local server:
    ngrok http 4000
  2. Copy the https forwarding URL from the ngrok output
  3. In your Twilio phone number settings, set the voice webhook to https://YOUR_NGROK_URL/webhooks/twilio/voice
  4. Call your Twilio number to test

Architecture

Caller → Twilio → POST /webhooks/twilio/voice
                      ↓
                  TwiML: welcome + <Gather> zip code
                      ↓
               POST /webhooks/twilio/gather
                      ↓
              ┌───────────────────────┐
              │  Processing Pipeline  │
              │                       │
              │  Zip → Geocoder (ETS) │
              │  Lat/Lon → NWS API    │
              │  Forecast → OpenRouter │
              │  Script → Voice (TTS) │
              └───────────┬───────────┘
                          ↓
                  TwiML: <Play> MP3 + <Hangup>

Modules

  • BehindTheWeather.Geocoder — Zip code to lat/lon lookup via ETS table loaded from bundled CSV
  • BehindTheWeather.Weather — NWS API client and forecast parsing
  • BehindTheWeather.Script — OpenRouter client; generates the narrator script
  • BehindTheWeather.Voice — Voice synthesis (ElevenLabs or Fish Audio); converts script to MP3
  • BehindTheWeather.AudioStore — Temporary MP3 storage with automatic cleanup

Error Handling

The app handles failures automatically so callers always get a response:

  • Invalid zip code — Re-prompts the caller
  • NWS API failure — "Temporarily unavailable" message + hangup
  • Script or voice generation failure — Falls back to Twilio <Say> with a plain weather summary
  • 15-second timeout — If the pipeline takes too long, serves the fallback

About

AI-powered weather forecast information service with natural text-to-speech, built with Elixir/Phoenix and Twilio

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors