Add per-channel hybrid audio spread spectrum and env feature toggles

Spread spectrum v2: independent per-channel embedding with round-robin
bit distribution, preserving spatial stereo/surround mix. Adaptive chip
tiers (256/512/1024) trade capacity for lossy codec robustness. LFE
channel skipped for 5.1+ layouts. v2 header (20B) with backward-
compatible v0 decode fallback.

Environment toggles (STEGASOO_AUDIO, STEGASOO_VIDEO) gate audio/video
features for minimal builds (e.g. Raspberry Pi image-only). Values:
auto (default, detect deps), 1/true (force on), 0/false (force off).

Web UI fixes: accordion defaults to step 1 on load, chevron arrow
styling, required attribute toggling for audio carrier type switch,
"Images & Mode" renamed to "Reference, Carrier, Mode".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-02-28 11:58:40 -05:00
parent 0248bec813
commit ef5a9ce9cb
41 changed files with 4281 additions and 732 deletions

View File

@@ -17,9 +17,8 @@ import json
import os
import secrets
from pathlib import Path
from typing import Optional
from fastapi import Depends, HTTPException, Security
from fastapi import HTTPException, Security
from fastapi.security import APIKeyHeader
# API key header name
@@ -55,7 +54,7 @@ def _load_keys(location: str = "user") -> dict:
try:
with open(keys_file) as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
except (OSError, json.JSONDecodeError):
return {"keys": [], "enabled": True}
return {"keys": [], "enabled": True}
@@ -101,11 +100,13 @@ def add_api_key(name: str, location: str = "user") -> str:
if existing["name"] == name:
raise ValueError(f"Key with name '{name}' already exists")
data["keys"].append({
"name": name,
"hash": key_hash,
"created": __import__("datetime").datetime.now().isoformat(),
})
data["keys"].append(
{
"name": name,
"hash": key_hash,
"created": __import__("datetime").datetime.now().isoformat(),
}
)
_save_keys(data, location)
@@ -204,12 +205,12 @@ def get_api_key_status() -> dict:
"keys": {
"user": user_keys,
"project": project_keys,
}
},
}
# FastAPI dependency for API key authentication
async def require_api_key(api_key: Optional[str] = Security(API_KEY_HEADER)) -> str:
async def require_api_key(api_key: str | None = Security(API_KEY_HEADER)) -> str:
"""
FastAPI dependency that requires a valid API key.
@@ -243,7 +244,7 @@ async def require_api_key(api_key: Optional[str] = Security(API_KEY_HEADER)) ->
return api_key
async def optional_api_key(api_key: Optional[str] = Security(API_KEY_HEADER)) -> Optional[str]:
async def optional_api_key(api_key: str | None = Security(API_KEY_HEADER)) -> str | None:
"""
FastAPI dependency that optionally validates API key.