sojorn/go-backend/internal/config/config.go
Patrick Britton 135bb7f08d feat: Audio overlay system — AudioLibraryScreen, Funkwhale proxy, ffmpeg audio mix
Go:
- GET /audio/library?q= — Funkwhale tracks proxy (503 until FUNKWHALE_BASE set)
- GET /audio/library/:trackId/listen — audio stream proxy
- FUNKWHALE_BASE config key added (env var)

Flutter:
- AudioLibraryScreen: Device tab (file_picker) + Library tab (Funkwhale)
- VideoStitchingService.stitchVideos(): audioOverlayPath + audioVolume params
  — second FFmpeg pass: amix with configurable volume, falls back if mix fails
- EnhancedQuipRecorderScreen: music button, audio chip + volume slider, wired to stitcher

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-17 16:00:55 -06:00

114 lines
4.1 KiB
Go

package config
import (
"os"
"strconv"
"github.com/joho/godotenv"
)
type Config struct {
Port string
Env string
LogLevel string
DatabaseURL string
JWTSecret string
CORSOrigins string
RateLimitRPS int
SMTPHost string
SMTPPort int
SMTPUser string
SMTPPass string
SMTPFrom string
SenderAPIToken string
SendPulseID string
SendPulseSecret string
R2SigningSecret string
R2PublicBaseURL string
FirebaseCredentialsFile string
R2AccountID string
R2APIToken string
R2ImgDomain string
R2VidDomain string
R2Endpoint string
R2AccessKey string
R2SecretKey string
R2MediaBucket string
R2VideoBucket string
APIBaseURL string
AppBaseURL string
OpenRouterAPIKey string
AIGatewayURL string
AIGatewayToken string
AzureOpenAIAPIKey string
AzureOpenAIEndpoint string
AzureOpenAIAPIVersion string
FunkwhaleBase string // e.g. "http://localhost:5001" — empty means not yet deployed
}
func LoadConfig() *Config {
// Try current directory first
err := godotenv.Load()
if err != nil {
// Try parent directory (common for VPS structure /opt/sojorn/.env while binary is in /opt/sojorn/go-backend)
_ = godotenv.Load("../.env")
// Try absolute path specified by user
_ = godotenv.Load("/opt/sojorn/.env")
}
return &Config{
Port: getEnv("PORT", "8080"),
Env: getEnv("ENV", "development"),
LogLevel: getEnv("LOG_LEVEL", "info"),
DatabaseURL: getEnv("DATABASE_URL", ""),
JWTSecret: getEnv("JWT_SECRET", ""),
CORSOrigins: getEnv("CORS_ORIGINS", "*"),
RateLimitRPS: getEnvInt("RATE_LIMIT_RPS", 10),
SMTPHost: getEnv("SMTP_HOST", "smtp.sender.net"),
SMTPPort: getEnvInt("SMTP_PORT", 587),
SMTPUser: getEnv("SMTP_USER", ""),
SMTPPass: getEnv("SMTP_PASS", ""),
SMTPFrom: getEnv("SMTP_FROM", "no-reply@sojorn.net"),
SenderAPIToken: getEnv("SENDER_API_TOKEN", ""),
SendPulseID: getEnv("SENDPULSE_ID", ""),
SendPulseSecret: getEnv("SENDPULSE_SECRET", ""),
R2SigningSecret: getEnv("R2_SIGNING_SECRET", ""),
// Default to the public CDN domain to avoid mixed-content/http defaults.
R2PublicBaseURL: getEnv("R2_PUBLIC_BASE_URL", "https://img.sojorn.net"),
FirebaseCredentialsFile: getEnv("FIREBASE_CREDENTIALS_FILE", "firebase-service-account.json"),
R2AccountID: getEnv("R2_ACCOUNT_ID", ""),
R2APIToken: getEnv("R2_API_TOKEN", ""),
R2ImgDomain: getEnv("R2_IMG_DOMAIN", "img.sojorn.net"),
R2VidDomain: getEnv("R2_VID_DOMAIN", "quips.sojorn.net"),
R2Endpoint: getEnv("R2_ENDPOINT", ""),
R2AccessKey: getEnv("R2_ACCESS_KEY", ""),
R2SecretKey: getEnv("R2_SECRET_KEY", ""),
R2MediaBucket: getEnv("R2_MEDIA_BUCKET", "sojorn-media"),
R2VideoBucket: getEnv("R2_VIDEO_BUCKET", "sojorn-videos"),
APIBaseURL: getEnv("API_BASE_URL", "https://api.sojorn.net"),
AppBaseURL: getEnv("APP_BASE_URL", "https://mp.ls"),
OpenRouterAPIKey: getEnv("OPENROUTER_API", ""),
AIGatewayURL: getEnv("AI_GATEWAY_URL", ""),
AIGatewayToken: getEnv("AI_GATEWAY_TOKEN", ""),
AzureOpenAIAPIKey: getEnv("AZURE_OPENAI_API_KEY", ""),
AzureOpenAIEndpoint: getEnv("AZURE_OPENAI_ENDPOINT", ""),
AzureOpenAIAPIVersion: getEnv("AZURE_OPENAI_API_VERSION", "2024-02-15-preview"),
FunkwhaleBase: getEnv("FUNKWHALE_BASE", ""),
}
}
func getEnv(key, fallback string) string {
if value, exists := os.LookupEnv(key); exists {
return value
}
return fallback
}
func getEnvInt(key string, fallback int) int {
valueStr := getEnv(key, "")
if value, err := strconv.Atoi(valueStr); err == nil {
return value
}
return fallback
}