Codex first iteration

This commit is contained in:
2026-07-12 02:56:51 +08:00
parent 16c626fbd7
commit 7cb409f5a6
20 changed files with 1771 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
package comicanimator
import (
"errors"
"os"
"strconv"
"time"
)
type Config struct {
OpenRouterAPIKey, OpenRouterBaseURL, OpenRouterSiteURL, OpenRouterAppName, PromptModel, VideoModel, VideoResolution, VideoAspectRatio, PublicBaseURL, SigningSecret, UploadDirectory, OutputDirectory string
VideoDuration int
GenerateAudio bool
PollInterval, JobTimeout, HTTPTimeout, SignedURLTTL time.Duration
MaxUploadBytes, MaxGeneratedVideoBytes int64
QueueCapacity int
}
func LoadConfigFromEnv() (Config, error) {
c := Config{OpenRouterAPIKey: os.Getenv("COMIC_ANIMATOR_OPENROUTER_API_KEY"), OpenRouterBaseURL: get("COMIC_ANIMATOR_OPENROUTER_BASE_URL", "https://openrouter.ai/api/v1"), OpenRouterSiteURL: os.Getenv("COMIC_ANIMATOR_OPENROUTER_SITE_URL"), OpenRouterAppName: get("COMIC_ANIMATOR_OPENROUTER_APP_NAME", "Preface Tools - Comic Animator"), PromptModel: os.Getenv("COMIC_ANIMATOR_PROMPT_MODEL"), VideoModel: os.Getenv("COMIC_ANIMATOR_VIDEO_MODEL"), VideoResolution: get("COMIC_ANIMATOR_VIDEO_RESOLUTION", "720p"), VideoAspectRatio: get("COMIC_ANIMATOR_VIDEO_ASPECT_RATIO", "16:9"), PublicBaseURL: os.Getenv("PUBLIC_BASE_URL"), SigningSecret: os.Getenv("COMIC_ANIMATOR_SIGNING_SECRET"), UploadDirectory: get("COMIC_ANIMATOR_UPLOAD_DIR", "data/comic-animator/uploads"), OutputDirectory: get("COMIC_ANIMATOR_OUTPUT_DIR", "data/comic-animator/outputs")}
var err error
c.VideoDuration, err = intenv("COMIC_ANIMATOR_VIDEO_DURATION", 6)
if err != nil {
return c, err
}
c.GenerateAudio, err = strconv.ParseBool(get("COMIC_ANIMATOR_GENERATE_AUDIO", "false"))
if err != nil {
return c, err
}
c.PollInterval, err = dur("COMIC_ANIMATOR_POLL_INTERVAL", "30s")
if err != nil {
return c, err
}
c.JobTimeout, err = dur("COMIC_ANIMATOR_JOB_TIMEOUT", "15m")
if err != nil {
return c, err
}
c.HTTPTimeout, err = dur("COMIC_ANIMATOR_HTTP_TIMEOUT", "60s")
if err != nil {
return c, err
}
c.SignedURLTTL, err = dur("COMIC_ANIMATOR_SIGNED_URL_TTL", "30m")
if err != nil {
return c, err
}
c.MaxUploadBytes, err = int64env("COMIC_ANIMATOR_MAX_UPLOAD_BYTES", 20971520)
if err != nil {
return c, err
}
c.MaxGeneratedVideoBytes, err = int64env("COMIC_ANIMATOR_MAX_VIDEO_BYTES", 536870912)
if err != nil {
return c, err
}
c.QueueCapacity, err = intenv("COMIC_ANIMATOR_QUEUE_CAPACITY", 100)
if err != nil {
return c, err
}
if c.OpenRouterAPIKey == "" || c.PromptModel == "" || c.VideoModel == "" || c.PublicBaseURL == "" || len(c.SigningSecret) < 32 {
return c, errors.New("Comic Animator OpenRouter key/models, PUBLIC_BASE_URL, and a 32+ character signing secret are required")
}
if c.VideoDuration < 1 || c.QueueCapacity < 1 || c.MaxUploadBytes < 1 || c.MaxGeneratedVideoBytes < 1 || c.PollInterval <= 0 || c.JobTimeout <= 0 || c.HTTPTimeout <= 0 || c.SignedURLTTL <= 0 {
return c, errors.New("Comic Animator numeric configuration is invalid")
}
return c, nil
}
func get(k, d string) string {
if v := os.Getenv(k); v != "" {
return v
}
return d
}
func dur(k, d string) (time.Duration, error) { return time.ParseDuration(get(k, d)) }
func intenv(k string, d int) (int, error) {
if os.Getenv(k) == "" {
return d, nil
}
return strconv.Atoi(os.Getenv(k))
}
func int64env(k string, d int64) (int64, error) {
if os.Getenv(k) == "" {
return d, nil
}
return strconv.ParseInt(os.Getenv(k), 10, 64)
}