{"repo": "allan10w/framebridge", "files": {"pkg/tools/tts_client_test.go": {"7a76c7b491d563e88aa452b5bc774be26e4fbecd": {"t": 1785746068.00991, "n": 4933, "h": "feb538bc4a10122f", "c": "package tools\n\nimport (\n\t\"testing\"\n\n\tappconfig \"github.com/difyz9/ytb2bili/internal/config\"\n\t\"go.uber.org/zap\"\n)\n\nfunc TestBuildRuntimeTTSConfigUsesAzureSection(t *testing.T) {\n\tcfg := &appconfig.AppConfig{\n\t\tLLM: appconfig.LLMConfig{\n\t\t\tBaseURL: \"https://api.deepseek.com\",\n\t\t\tAPIKey: \"sk-test\",\n\t\t},\n\t\tTTS: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t},\n\t\tAzureTTS: appconfig.AzureTTSConfig{\n\t\t\tSubscriptionKey: \"azure-subscription\",\n\t\t\tRegion: \"eastasia\",\n\t\t},\n\t\tTencentTTS: appconfig.TencentTTSConfig{\n\t\t\tSecretID: \"tencent-secret-id\",\n\t\t\tSecretKey: \"tencent-secret-key\",\n\t\t\tRegion: \"ap-guangzhou\",\n\t\t},\n\t}\n\n\truntimeCfg := buildRuntimeTTSConfig(cfg)\n\tif runtimeCfg.AzureSubscriptionKey != \"azure-subscription\" {\n\t\tt.Fatalf(\"expected azure subscription key to be loaded, got %q\", runtimeCfg.AzureSubscriptionKey)\n\t}\n\tif runtimeCfg.AzureRegion != \"eastasia\" {\n\t\tt.Fatalf(\"expected azure region to be loaded, got %q\", runtimeCfg.AzureRegion)\n\t}\n\tif runtimeCfg.TencentSecretID != \"tencent-secret-id\" || runtimeCfg.TencentSecretKey != \"tencent-secret-key\" {\n\t\tt.Fatalf(\"expected Tencent credentials to be loaded\")\n\t}\n\tif runtimeCfg.TencentRegion != \"ap-guangzhou\" {\n\t\tt.Fatalf(\"expected Tencent region to be loaded, got %q\", runtimeCfg.TencentRegion)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_LegacyVoiceValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(\"zh-CN-YunxiNeural\")\n\tif !ok {\n\t\tt.Fatal(\"expected legacy voice value to be parsed\")\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice to be parsed, got %q\", config.Voice)\n\t}\n\tif config.Provider != \"\" {\n\t\tt.Fatalf(\"expected provider to remain empty, got %q\", config.Provider)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_JSONValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(`{\"provider\":\"tencent\",\"voice_name\":\"zh-CN-YunxiNeural\",\"language\":\"zh-CN\",\"format\":\"mp3\",\"search\":\"Yunxi\",\"rate\":1.25,\"volume\":88,\"pitch\":3,\"timeout_seconds\":45}`)\n\tif !ok {\n\t\tt.Fatal(\"expected json config to be parsed\")\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider from json, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice from json, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search from json, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format from json, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate from json, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume from json, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch from json, got %v\", config.Pitch)\n\t}\n\tif config.TimeoutSeconds != 45 {\n\t\tt.Fatalf(\"expected timeout from json, got %v\", config.TimeoutSeconds)\n\t}\n}\n\nfunc TestMergeConfig_UsesUserOverridesAndKeepsGlobalCredentials(t *testing.T) {\n\tclient := newTTSClientWithConfig(TTSConfig{\n\t\tBaseURL: \"https://open.ytb2bili.com\",\n\t\tAPIKey: \"sk-test\",\n\t\tProjectID: \"project-default\",\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t\tFormat: \"audio-24khz-96kbitrate-mono-mp3\",\n\t\t\tRate: 1,\n\t\t\tVolume: 100,\n\t\t},\n\t}, nil, zap.NewNop())\n\n\tconfig := client.mergeConfig(client.config, TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"tencent\",\n\t\t\tVoice: \"zh-CN-YunxiNeural\",\n\t\t\tSearch: \"Yunxi\",\n\t\t\tFormat: \"mp3\",\n\t\t\tRate: 1.25,\n\t\t\tVolume: 88,\n\t\t\tPitch: 3,\n\t\t},\n\t})\n\tif config.BaseURL != \"https://open.ytb2bili.com\" {\n\t\tt.Fatalf(\"expected baseURL to stay global, got %q\", config.BaseURL)\n\t}\n\tif config.APIKey != \"sk-test\" {\n\t\tt.Fatalf(\"expected apiKey to stay global, got %q\", config.APIKey)\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider override, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice override, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search override, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format override, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate override, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume override, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch override, got %v\", config.Pitch)\n\t}\n}\n\nfunc TestNormalizeTTSConfig_ClampsVolumeIntoSupportedRange(t *testing.T) {\n\tconfig := normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: 250,\n\t\t},\n\t})\n\tif config.Volume != 100 {\n\t\tt.Fatalf(\"expected volume to be clamped to 100, got %v\", config.Volume)\n\t}\n\n\tconfig = normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: -15,\n\t\t},\n\t})\n\tif config.Volume != 0 {\n\t\tt.Fatalf(\"expected negative volume to be clamped to 0, got %v\", config.Volume)\n\t}\n}\n"}, "d2e824162a0bdce4a56aebc045fb0ea8123a4b1b": {"t": 1785759465.5841548, "n": 4933, "h": "feb538bc4a10122f", "c": "package tools\n\nimport (\n\t\"testing\"\n\n\tappconfig \"github.com/difyz9/ytb2bili/internal/config\"\n\t\"go.uber.org/zap\"\n)\n\nfunc TestBuildRuntimeTTSConfigUsesAzureSection(t *testing.T) {\n\tcfg := &appconfig.AppConfig{\n\t\tLLM: appconfig.LLMConfig{\n\t\t\tBaseURL: \"https://api.deepseek.com\",\n\t\t\tAPIKey: \"sk-test\",\n\t\t},\n\t\tTTS: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t},\n\t\tAzureTTS: appconfig.AzureTTSConfig{\n\t\t\tSubscriptionKey: \"azure-subscription\",\n\t\t\tRegion: \"eastasia\",\n\t\t},\n\t\tTencentTTS: appconfig.TencentTTSConfig{\n\t\t\tSecretID: \"tencent-secret-id\",\n\t\t\tSecretKey: \"tencent-secret-key\",\n\t\t\tRegion: \"ap-guangzhou\",\n\t\t},\n\t}\n\n\truntimeCfg := buildRuntimeTTSConfig(cfg)\n\tif runtimeCfg.AzureSubscriptionKey != \"azure-subscription\" {\n\t\tt.Fatalf(\"expected azure subscription key to be loaded, got %q\", runtimeCfg.AzureSubscriptionKey)\n\t}\n\tif runtimeCfg.AzureRegion != \"eastasia\" {\n\t\tt.Fatalf(\"expected azure region to be loaded, got %q\", runtimeCfg.AzureRegion)\n\t}\n\tif runtimeCfg.TencentSecretID != \"tencent-secret-id\" || runtimeCfg.TencentSecretKey != \"tencent-secret-key\" {\n\t\tt.Fatalf(\"expected Tencent credentials to be loaded\")\n\t}\n\tif runtimeCfg.TencentRegion != \"ap-guangzhou\" {\n\t\tt.Fatalf(\"expected Tencent region to be loaded, got %q\", runtimeCfg.TencentRegion)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_LegacyVoiceValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(\"zh-CN-YunxiNeural\")\n\tif !ok {\n\t\tt.Fatal(\"expected legacy voice value to be parsed\")\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice to be parsed, got %q\", config.Voice)\n\t}\n\tif config.Provider != \"\" {\n\t\tt.Fatalf(\"expected provider to remain empty, got %q\", config.Provider)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_JSONValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(`{\"provider\":\"tencent\",\"voice_name\":\"zh-CN-YunxiNeural\",\"language\":\"zh-CN\",\"format\":\"mp3\",\"search\":\"Yunxi\",\"rate\":1.25,\"volume\":88,\"pitch\":3,\"timeout_seconds\":45}`)\n\tif !ok {\n\t\tt.Fatal(\"expected json config to be parsed\")\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider from json, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice from json, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search from json, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format from json, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate from json, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume from json, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch from json, got %v\", config.Pitch)\n\t}\n\tif config.TimeoutSeconds != 45 {\n\t\tt.Fatalf(\"expected timeout from json, got %v\", config.TimeoutSeconds)\n\t}\n}\n\nfunc TestMergeConfig_UsesUserOverridesAndKeepsGlobalCredentials(t *testing.T) {\n\tclient := newTTSClientWithConfig(TTSConfig{\n\t\tBaseURL: \"https://open.ytb2bili.com\",\n\t\tAPIKey: \"sk-test\",\n\t\tProjectID: \"project-default\",\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t\tFormat: \"audio-24khz-96kbitrate-mono-mp3\",\n\t\t\tRate: 1,\n\t\t\tVolume: 100,\n\t\t},\n\t}, nil, zap.NewNop())\n\n\tconfig := client.mergeConfig(client.config, TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"tencent\",\n\t\t\tVoice: \"zh-CN-YunxiNeural\",\n\t\t\tSearch: \"Yunxi\",\n\t\t\tFormat: \"mp3\",\n\t\t\tRate: 1.25,\n\t\t\tVolume: 88,\n\t\t\tPitch: 3,\n\t\t},\n\t})\n\tif config.BaseURL != \"https://open.ytb2bili.com\" {\n\t\tt.Fatalf(\"expected baseURL to stay global, got %q\", config.BaseURL)\n\t}\n\tif config.APIKey != \"sk-test\" {\n\t\tt.Fatalf(\"expected apiKey to stay global, got %q\", config.APIKey)\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider override, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice override, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search override, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format override, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate override, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume override, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch override, got %v\", config.Pitch)\n\t}\n}\n\nfunc TestNormalizeTTSConfig_ClampsVolumeIntoSupportedRange(t *testing.T) {\n\tconfig := normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: 250,\n\t\t},\n\t})\n\tif config.Volume != 100 {\n\t\tt.Fatalf(\"expected volume to be clamped to 100, got %v\", config.Volume)\n\t}\n\n\tconfig = normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: -15,\n\t\t},\n\t})\n\tif config.Volume != 0 {\n\t\tt.Fatalf(\"expected negative volume to be clamped to 0, got %v\", config.Volume)\n\t}\n}\n"}, "17e23548791efcf58f438cc9dfaf85d701fa64e8": {"t": 1785759466.9262671, "n": 4478, "h": "0c992d5683e799db", "c": "package tools\n\nimport (\n\t\"testing\"\n\n\tappconfig \"github.com/difyz9/ytb2bili/internal/config\"\n\t\"go.uber.org/zap\"\n)\n\nfunc TestBuildRuntimeTTSConfigUsesAzureSection(t *testing.T) {\n\tcfg := &appconfig.AppConfig{\n\t\tLLM: appconfig.LLMConfig{\n\t\t\tBaseURL: \"https://api.deepseek.com\",\n\t\t\tAPIKey: \"sk-test\",\n\t\t},\n\t\tTTS: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t},\n\t\tAzureTTS: appconfig.AzureTTSConfig{\n\t\t\tSubscriptionKey: \"azure-subscription\",\n\t\t\tRegion: \"eastasia\",\n\t\t},\n\t}\n\n\truntimeCfg := buildRuntimeTTSConfig(cfg)\n\tif runtimeCfg.AzureSubscriptionKey != \"azure-subscription\" {\n\t\tt.Fatalf(\"expected azure subscription key to be loaded, got %q\", runtimeCfg.AzureSubscriptionKey)\n\t}\n\tif runtimeCfg.AzureRegion != \"eastasia\" {\n\t\tt.Fatalf(\"expected azure region to be loaded, got %q\", runtimeCfg.AzureRegion)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_LegacyVoiceValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(\"zh-CN-YunxiNeural\")\n\tif !ok {\n\t\tt.Fatal(\"expected legacy voice value to be parsed\")\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice to be parsed, got %q\", config.Voice)\n\t}\n\tif config.Provider != \"\" {\n\t\tt.Fatalf(\"expected provider to remain empty, got %q\", config.Provider)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_JSONValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(`{\"provider\":\"tencent\",\"voice_name\":\"zh-CN-YunxiNeural\",\"language\":\"zh-CN\",\"format\":\"mp3\",\"search\":\"Yunxi\",\"rate\":1.25,\"volume\":88,\"pitch\":3,\"timeout_seconds\":45}`)\n\tif !ok {\n\t\tt.Fatal(\"expected json config to be parsed\")\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider from json, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice from json, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search from json, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format from json, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate from json, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume from json, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch from json, got %v\", config.Pitch)\n\t}\n\tif config.TimeoutSeconds != 45 {\n\t\tt.Fatalf(\"expected timeout from json, got %v\", config.TimeoutSeconds)\n\t}\n}\n\nfunc TestMergeConfig_UsesUserOverridesAndKeepsGlobalCredentials(t *testing.T) {\n\tclient := newTTSClientWithConfig(TTSConfig{\n\t\tBaseURL: \"https://open.ytb2bili.com\",\n\t\tAPIKey: \"sk-test\",\n\t\tProjectID: \"project-default\",\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t\tFormat: \"audio-24khz-96kbitrate-mono-mp3\",\n\t\t\tRate: 1,\n\t\t\tVolume: 100,\n\t\t},\n\t}, nil, zap.NewNop())\n\n\tconfig := client.mergeConfig(client.config, TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"tencent\",\n\t\t\tVoice: \"zh-CN-YunxiNeural\",\n\t\t\tSearch: \"Yunxi\",\n\t\t\tFormat: \"mp3\",\n\t\t\tRate: 1.25,\n\t\t\tVolume: 88,\n\t\t\tPitch: 3,\n\t\t},\n\t})\n\tif config.BaseURL != \"https://open.ytb2bili.com\" {\n\t\tt.Fatalf(\"expected baseURL to stay global, got %q\", config.BaseURL)\n\t}\n\tif config.APIKey != \"sk-test\" {\n\t\tt.Fatalf(\"expected apiKey to stay global, got %q\", config.APIKey)\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider override, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice override, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search override, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format override, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate override, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume override, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch override, got %v\", config.Pitch)\n\t}\n}\n\nfunc TestNormalizeTTSConfig_ClampsVolumeIntoSupportedRange(t *testing.T) {\n\tconfig := normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: 250,\n\t\t},\n\t})\n\tif config.Volume != 100 {\n\t\tt.Fatalf(\"expected volume to be clamped to 100, got %v\", config.Volume)\n\t}\n\n\tconfig = normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: -15,\n\t\t},\n\t})\n\tif config.Volume != 0 {\n\t\tt.Fatalf(\"expected negative volume to be clamped to 0, got %v\", config.Volume)\n\t}\n}\n"}, "7347c5df85cf7dd5ab482739d9655f041fc74236": {"t": 1785759468.5210142, "n": 4478, "h": "fa6dc8a30d5526f5", "c": "package tools\n\nimport (\n\t\"testing\"\n\n\tappconfig \"github.com/zolagz/ytb2bili/internal/config\"\n\t\"go.uber.org/zap\"\n)\n\nfunc TestBuildRuntimeTTSConfigUsesAzureSection(t *testing.T) {\n\tcfg := &appconfig.AppConfig{\n\t\tLLM: appconfig.LLMConfig{\n\t\t\tBaseURL: \"https://api.deepseek.com\",\n\t\t\tAPIKey: \"sk-test\",\n\t\t},\n\t\tTTS: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t},\n\t\tAzureTTS: appconfig.AzureTTSConfig{\n\t\t\tSubscriptionKey: \"azure-subscription\",\n\t\t\tRegion: \"eastasia\",\n\t\t},\n\t}\n\n\truntimeCfg := buildRuntimeTTSConfig(cfg)\n\tif runtimeCfg.AzureSubscriptionKey != \"azure-subscription\" {\n\t\tt.Fatalf(\"expected azure subscription key to be loaded, got %q\", runtimeCfg.AzureSubscriptionKey)\n\t}\n\tif runtimeCfg.AzureRegion != \"eastasia\" {\n\t\tt.Fatalf(\"expected azure region to be loaded, got %q\", runtimeCfg.AzureRegion)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_LegacyVoiceValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(\"zh-CN-YunxiNeural\")\n\tif !ok {\n\t\tt.Fatal(\"expected legacy voice value to be parsed\")\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice to be parsed, got %q\", config.Voice)\n\t}\n\tif config.Provider != \"\" {\n\t\tt.Fatalf(\"expected provider to remain empty, got %q\", config.Provider)\n\t}\n}\n\nfunc TestParseStoredUserTTSConfig_JSONValue(t *testing.T) {\n\tconfig, ok := parseStoredUserTTSConfig(`{\"provider\":\"tencent\",\"voice_name\":\"zh-CN-YunxiNeural\",\"language\":\"zh-CN\",\"format\":\"mp3\",\"search\":\"Yunxi\",\"rate\":1.25,\"volume\":88,\"pitch\":3,\"timeout_seconds\":45}`)\n\tif !ok {\n\t\tt.Fatal(\"expected json config to be parsed\")\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider from json, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice from json, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search from json, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format from json, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate from json, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume from json, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch from json, got %v\", config.Pitch)\n\t}\n\tif config.TimeoutSeconds != 45 {\n\t\tt.Fatalf(\"expected timeout from json, got %v\", config.TimeoutSeconds)\n\t}\n}\n\nfunc TestMergeConfig_UsesUserOverridesAndKeepsGlobalCredentials(t *testing.T) {\n\tclient := newTTSClientWithConfig(TTSConfig{\n\t\tBaseURL: \"https://open.ytb2bili.com\",\n\t\tAPIKey: \"sk-test\",\n\t\tProjectID: \"project-default\",\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"auto\",\n\t\t\tVoice: \"zh-CN-XiaoxiaoNeural\",\n\t\t\tLocale: \"zh-CN\",\n\t\t\tFormat: \"audio-24khz-96kbitrate-mono-mp3\",\n\t\t\tRate: 1,\n\t\t\tVolume: 100,\n\t\t},\n\t}, nil, zap.NewNop())\n\n\tconfig := client.mergeConfig(client.config, TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tProvider: \"tencent\",\n\t\t\tVoice: \"zh-CN-YunxiNeural\",\n\t\t\tSearch: \"Yunxi\",\n\t\t\tFormat: \"mp3\",\n\t\t\tRate: 1.25,\n\t\t\tVolume: 88,\n\t\t\tPitch: 3,\n\t\t},\n\t})\n\tif config.BaseURL != \"https://open.ytb2bili.com\" {\n\t\tt.Fatalf(\"expected baseURL to stay global, got %q\", config.BaseURL)\n\t}\n\tif config.APIKey != \"sk-test\" {\n\t\tt.Fatalf(\"expected apiKey to stay global, got %q\", config.APIKey)\n\t}\n\tif config.Provider != \"tencent\" {\n\t\tt.Fatalf(\"expected provider override, got %q\", config.Provider)\n\t}\n\tif config.Voice != \"zh-CN-YunxiNeural\" {\n\t\tt.Fatalf(\"expected voice override, got %q\", config.Voice)\n\t}\n\tif config.Search != \"Yunxi\" {\n\t\tt.Fatalf(\"expected search override, got %q\", config.Search)\n\t}\n\tif config.Format != \"mp3\" {\n\t\tt.Fatalf(\"expected format override, got %q\", config.Format)\n\t}\n\tif config.Rate != 1.25 {\n\t\tt.Fatalf(\"expected rate override, got %v\", config.Rate)\n\t}\n\tif config.Volume != 88 {\n\t\tt.Fatalf(\"expected volume override, got %v\", config.Volume)\n\t}\n\tif config.Pitch != 3 {\n\t\tt.Fatalf(\"expected pitch override, got %v\", config.Pitch)\n\t}\n}\n\nfunc TestNormalizeTTSConfig_ClampsVolumeIntoSupportedRange(t *testing.T) {\n\tconfig := normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: 250,\n\t\t},\n\t})\n\tif config.Volume != 100 {\n\t\tt.Fatalf(\"expected volume to be clamped to 100, got %v\", config.Volume)\n\t}\n\n\tconfig = normalizeTTSConfig(TTSConfig{\n\t\tTTSConfig: appconfig.TTSConfig{\n\t\t\tVolume: -15,\n\t\t},\n\t})\n\tif config.Volume != 0 {\n\t\tt.Fatalf(\"expected negative volume to be clamped to 0, got %v\", config.Volume)\n\t}\n}\n"}}, "config.toml.example": {"7a76c7b491d563e88aa452b5bc774be26e4fbecd": {"t": 1785746804.8284142, "n": 3282, "h": "7d485beea55586af", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 可以自定义登录账号\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"123456\"\n\n\n\n\n# 浏览器插件提交必须启用 HMAC 签名验证。请将下列两个密钥替换成各自\n# 随机生成的 32+ 字符值,并在支持签名的插件中配置相同的 app_id/app_secret。\n[api_auth]\nenabled = true\napp_id = \"ytb2bili_extension\"\napp_secret = \"replace-with-a-random-extension-hmac-secret\"\ncookies_decrypt_key = \"replace-with-a-separate-32-byte-cookie-key\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# ==========================================================================\n# 宿主机 Apple Silicon ASR(Docker 通过 host.docker.internal 调用)\n# ==========================================================================\n[asr]\n# local_mlx_whisper 使用 host_asr/ 的 MLX Whisper + WhisperX CPU 服务。\n# bcut 仍可作为 provider 或显式 fallback_provider 使用。\nprovider = \"local_mlx_whisper\"\nfallback_provider = \"\" # 需要 BCut 回退时设置为 \"bcut\"\nbase_url = \"http://host.docker.internal:9000/v1\"\napi_key = \"\"\nmodel = \"mlx-community/whisper-large-v3-turbo\"\n# 已知源语言必须填写,例如 \"en\";留空时仅在任务未指定源语言时自动检测。\nlanguage = \"\"\ntimeout_seconds = 1800\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxxxxxxxxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n\n[tencent_tts]\nsecret_id = \"\" # Tencent Cloud SecretId\nsecret_key = \"\" # Tencent Cloud SecretKey\nregion = \"ap-guangzhou\" # Tencent Cloud region\n"}, "d2e824162a0bdce4a56aebc045fb0ea8123a4b1b": {"t": 1785759463.5179834, "n": 3282, "h": "7d485beea55586af", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 可以自定义登录账号\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"123456\"\n\n\n\n\n# 浏览器插件提交必须启用 HMAC 签名验证。请将下列两个密钥替换成各自\n# 随机生成的 32+ 字符值,并在支持签名的插件中配置相同的 app_id/app_secret。\n[api_auth]\nenabled = true\napp_id = \"ytb2bili_extension\"\napp_secret = \"replace-with-a-random-extension-hmac-secret\"\ncookies_decrypt_key = \"replace-with-a-separate-32-byte-cookie-key\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# ==========================================================================\n# 宿主机 Apple Silicon ASR(Docker 通过 host.docker.internal 调用)\n# ==========================================================================\n[asr]\n# local_mlx_whisper 使用 host_asr/ 的 MLX Whisper + WhisperX CPU 服务。\n# bcut 仍可作为 provider 或显式 fallback_provider 使用。\nprovider = \"local_mlx_whisper\"\nfallback_provider = \"\" # 需要 BCut 回退时设置为 \"bcut\"\nbase_url = \"http://host.docker.internal:9000/v1\"\napi_key = \"\"\nmodel = \"mlx-community/whisper-large-v3-turbo\"\n# 已知源语言必须填写,例如 \"en\";留空时仅在任务未指定源语言时自动检测。\nlanguage = \"\"\ntimeout_seconds = 1800\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxxxxxxxxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n\n[tencent_tts]\nsecret_id = \"\" # Tencent Cloud SecretId\nsecret_key = \"\" # Tencent Cloud SecretKey\nregion = \"ap-guangzhou\" # Tencent Cloud region\n"}, "7347c5df85cf7dd5ab482739d9655f041fc74236": {"t": 1785759464.8634408, "n": 2502, "h": "ddfcff0dca417f7a", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 可以自定义登录账号\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"123456\"\n\n\n\n\n## 这里不要改\n[api_auth]\nenabled = false\napp_id = \"ytb2bili_extension\"\napp_secret = \"ytb2bili_secret_2026\"\ncookies_decrypt_key = \"59e7052041ce4bd6aff82f6a0bca9cde\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# 水印字体文件路径(可选;用于非会员水印 drawtext fontfile)\nwatermark_font_file = \"/app/fonts/watermark.ttf\"\n\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxxxxxxxxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n"}, "80694b6b248d350b577abf6cd64b9ca4fef62673": {"t": 1785759467.6383412, "n": 4339, "h": "1aed9248b5c5435b", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 5688 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"sqlite\" # 数据库类型: sqlite, mysql, postgresql\npath = \"ytb2bili.db\" # SQLite 数据库文件路径\nauto_migrate = true # 是否自动迁移数据库表结构\ntable_prefix = \"\" # 表名前缀(可选)\n\n# MySQL 配置示例(取消注释并修改以使用 MySQL)\n# type = \"mysql\"\n# host = \"127.0.0.1\"\n# port = 3306\n# user = \"root\"\n# password = \"your_password\"\n# dbname = \"ytb2ibili\"\n# timezone = \"Asia/Shanghai\"\n\n# PostgreSQL 配置示例(取消注释并修改以使用 PostgreSQL)\n# type = \"postgresql\"\n# host = \"127.0.0.1\"\n# port = 5432\n# user = \"postgres\"\n# password = \"your_password\"\n# dbname = \"ytb2bili\"\n# sslmode = \"disable\"\n# timezone = \"UTC\"\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/local/bin/ffmpeg\"\n\n\n# 代理地址(可选,用于加速下载)\n# proxy_url = \"http://127.0.0.1:7890\"\n\n# 微软语音服务配置(可选,用于旧版翻译功能)\n# speech_key = \"your_azure_speech_key\"\n# speech_region = \"eastasia\"\n\n# LLM 翻译配置\nllm_translation_enabled = false # 是否启用 LLM 批量翻译(推荐,替代微软翻译)\nllm_translation_batch_size = 25 # 批量翻译每批句子数\nllm_translation_max_workers = 3 # 并发工作者数量\nllm_translation_context_size = 2 # 上下文窗口大小\nllm_translation_source_lang = \"en\" # 源语言代码\nllm_translation_target_lang = \"zh-Hans\" # 目标语言代码\n\n# TTS 字幕音频合成配置\ntts_enabled = false # 是否启用字幕音频合成\n\n# ============================================================================\n# Agent & LLM 配置\n# ============================================================================\n[agent]\nname = \"ytb2bili_agent\" # Agent 名称\n\n[agent.llm]\nprovider = \"openai\" # LLM 提供商: openai, deepseek, openrouter 等\napi_key = \"your_api_key_here\" # LLM API 密钥(必需)\nmodel = \"gpt-4\" # 使用的模型名称\n# base_url = \"https://api.openai.com/v1\" # 自定义 API 地址(可选)\n\n# OpenRouter 示例\n# provider = \"openrouter\"\n# api_key = \"sk-or-v1-...\"\n# base_url = \"https://openrouter.ai/api/v1\"\n# model = \"anthropic/claude-3-sonnet\"\n\n# DeepSeek 示例\n# provider = \"deepseek\"\n# api_key = \"sk-...\"\n# base_url = \"https://api.deepseek.com/v1\"\n# model = \"deepseek-chat\"\n\n\n\n# Google Gemini 示例(base_url 可省略,程序自动设置 OpenAI 兼容端点)\n# provider = \"gemini\"\n# api_key = \"AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\"\n# model = \"gemini-2.0-flash\" # 可选: gemini-2.0-flash, gemini-1.5-pro, gemini-2.0-flash-thinking-exp\n# base_url = \"https://generativelanguage.googleapis.com/v1beta/openai\" # 可省略,程序自动填充\n\n\n\n\n\n\n\n# ============================================================================\n# 自动更新配置\n# ============================================================================\n[updater]\nenabled = true # 是否启用更新检查\nauto_update = false # 是否自动更新(建议设为 false,手动更新更安全)\ncheck_interval = 24 # 检查更新间隔(小时),0 表示禁用\n# update_url = \"https://api.github.com/repos/zolagz/ytb2bili/releases/latest\"\n# current_version = \"0.0.1\"\n\n# ============================================================================\n# TTS 服务配置(可选,用于语音合成)\n# ============================================================================\n[tts]\n# base_url = \"https://tts-api.com\"\n# app_id = \"your_app_id\"\n# app_secret = \"your_app_secret\"\n\n# ============================================================================\n# 腾讯云 COS 存储配置(可选,用于云端存储)\n# ============================================================================\n[tencos]\nenabled = false # 是否启用腾讯云 COS 存储\n# cos_bucket_url = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\"\n# cos_secret_id = \"your_secret_id\"\n# cos_secret_key = \"your_secret_key\"\n# cos_region = \"ap-guangzhou\"\n# cos_bucket = \"your-bucket-name\"\n# sub_app_id = \"your_app_id\"\n"}, "ddcb1c97778e4eb0bdd8f417a0a7e09590227823": {"t": 1785759469.0139496, "n": 4611, "h": "2298afd49dd38e61", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 5688 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"sqlite\" # 数据库类型: sqlite, mysql, postgresql\npath = \"ytb2bili.db\" # SQLite 数据库文件路径\nauto_migrate = true # 是否自动迁移数据库表结构\ntable_prefix = \"\" # 表名前缀(可选)\n\n# MySQL 配置示例(取消注释并修改以使用 MySQL)\n# type = \"mysql\"\n# host = \"127.0.0.1\"\n# port = 3306\n# user = \"root\"\n# password = \"your_password\"\n# dbname = \"ytb2ibili\"\n# timezone = \"Asia/Shanghai\"\n\n# PostgreSQL 配置示例(取消注释并修改以使用 PostgreSQL)\n# type = \"postgresql\"\n# host = \"127.0.0.1\"\n# port = 5432\n# user = \"postgres\"\n# password = \"your_password\"\n# dbname = \"ytb2bili\"\n# sslmode = \"disable\"\n# timezone = \"UTC\"\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/local/bin/ffmpeg\"\n\n\n# 代理地址(可选,用于加速下载)\n# proxy_url = \"http://127.0.0.1:7890\"\n\n# 微软语音服务配置(可选,用于旧版翻译功能)\n# speech_key = \"your_azure_speech_key\"\n# speech_region = \"eastasia\"\n\n# LLM 翻译配置\nllm_translation_enabled = false # 是否启用 LLM 批量翻译(推荐,替代微软翻译)\nllm_translation_batch_size = 25 # 批量翻译每批句子数\nllm_translation_max_workers = 3 # 并发工作者数量\nllm_translation_context_size = 2 # 上下文窗口大小\nllm_translation_source_lang = \"en\" # 源语言代码\nllm_translation_target_lang = \"zh-Hans\" # 目标语言代码\n\n# TTS 字幕音频合成配置\ntts_enabled = false # 是否启用字幕音频合成\n\n# ============================================================================\n# Agent & LLM 配置\n# ============================================================================\n[agent]\nname = \"ytb2bili_agent\" # Agent 名称\n\n[agent.llm]\nprovider = \"openai\" # LLM 提供商: openai, deepseek, openrouter 等\napi_key = \"your_api_key_here\" # LLM API 密钥(必需)\nmodel = \"gpt-4\" # 使用的模型名称\n# base_url = \"https://api.openai.com/v1\" # 自定义 API 地址(可选)\n\n# OpenRouter 示例\n# provider = \"openrouter\"\n# api_key = \"sk-or-v1-...\"\n# base_url = \"https://openrouter.ai/api/v1\"\n# model = \"anthropic/claude-3-sonnet\"\n\n# DeepSeek 示例\n# provider = \"deepseek\"\n# api_key = \"sk-...\"\n# base_url = \"https://api.deepseek.com/v1\"\n# model = \"deepseek-chat\"\n\n# ============================================================================\n# Firebase 配置(可选,用于用户认证)\n# ============================================================================\n[firebase]\nenabled = false # 是否启用 Firebase 认证\n# credentials_path = \"/path/to/firebase-credentials.json\"\n# project_id = \"your-project-id\"\n\n# ============================================================================\n# TikHub API 配置(可选,用于抖音相关功能)\n# ============================================================================\n[tikhub]\n# api_key = \"your_tikhub_api_key\"\n# base_url = \"https://api.tikhub.io\"\n\n\n\n\n# ============================================================================\n# 自动更新配置\n# ============================================================================\n[updater]\nenabled = true # 是否启用更新检查\nauto_update = false # 是否自动更新(建议设为 false,手动更新更安全)\ncheck_interval = 24 # 检查更新间隔(小时),0 表示禁用\n# update_url = \"https://api.github.com/repos/zolagz/ytb2bili/releases/latest\"\n# current_version = \"0.0.1\"\n\n# ============================================================================\n# TTS 服务配置(可选,用于语音合成)\n# ============================================================================\n[tts]\n# base_url = \"https://tts-api.com\"\n# app_id = \"your_app_id\"\n# app_secret = \"your_app_secret\"\n\n# ============================================================================\n# 腾讯云 COS 存储配置(可选,用于云端存储)\n# ============================================================================\n[tencos]\nenabled = false # 是否启用腾讯云 COS 存储\n# cos_bucket_url = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\"\n# cos_secret_id = \"your_secret_id\"\n# cos_secret_key = \"your_secret_key\"\n# cos_region = \"ap-guangzhou\"\n# cos_bucket = \"your-bucket-name\"\n# sub_app_id = \"your_app_id\"\n"}, "b63a7f8366f6551a82a04322aecc8ac66ee0904b": {"t": 1785759471.1433947, "n": 2558, "h": "d0e6b17fced6d516", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"./media\"\ndata_path = \"./data\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"mysql\"\n host = \"localhost\"\n port = 3306\n username = \"root\"\n password = \"your_password\"\n database = \"bili_up\"\n ssl_mode = \"\"\n timezone = \"Asia/Shanghai\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[GeminiConfig]\n enabled = false # 是否启用Gemini服务\n api_key = \"\" # Google AI API密钥(从 https://aistudio.google.com/app/apikey 获取)\n model = \"gemini-2.5-flash\" # 使用的模型(gemini-2.5-flash 快速, gemini-2.5-pro 强大)\n timeout = 120 # 超时时间(秒)\n max_tokens = 8000 # 最大输出token数\n use_for_metadata = false # 是否使用Gemini生成元数据(优先于DeepSeek)\n analyze_video = true # 是否分析视频文件(true=多模态分析,false=仅文本)\n video_sample_frames = 0 # 视频采样帧数(0=上传完整视频)\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n[BilibiliConfig]\n copyright = 2 # 1=自制, 2=转载\n source = \"YouTube\" # 转载来源\n no_reprint = 1 # 0=允许转载, 1=禁止转载\n use_original_title = true # true=使用原视频标题, false=使用AI生成标题\n use_original_desc = false # true=使用原视频描述, false=使用AI生成描述\n custom_title_template = \"\" # 自定义标题模板(可选),支持变量: {original_title}, {ai_title}\n # 示例: \"{original_title}【中文字幕】\" 或 \"【原神MMD】{ai_title}\"\n custom_desc_template = \"\" # 自定义描述模板(可选),支持变量: {original_desc}, {ai_desc}\n \n # 新增配置项\n tid = 122 # 分区ID(122=日常,138=搞笑,详见B站分区列表)\n dynamic = \"发布了新视频!\" # 动态文本\n open_elec = 0 # 是否开启充电面板 0=关闭, 1=开启\n selection_reserve = 0 # 参与活动ID(0表示不参与,暂不被SDK支持)\n up_selection_reply = 0 # 是否展示推荐评论 0=关闭, 1=开启(暂不被SDK支持)\n up_close_reply = 0 # 是否关闭评论 0=开启评论, 1=关闭评论(暂不被SDK支持)\n up_close_reward = 0 # 是否关闭打赏 0=开启, 1=关闭(暂不被SDK支持)\n\n # 自定义描述模板示例:\n # custom_desc_template = \"\"\"\n # 【视频内容】\n # {ai_desc}\n # \n # 【原视频描述】\n # {original_desc}\n # \"\"\"\n"}, "71b8e40a3cfe765bd31876b125c7553cf4c38146": {"t": 1785759472.6025252, "n": 2748, "h": "5509868e4d5937d1", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"./media\"\ndata_path = \"./data\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"mysql\"\n host = \"localhost\"\n port = 3306\n username = \"root\"\n password = \"your_password\"\n database = \"bili_up\"\n ssl_mode = \"\"\n timezone = \"Asia/Shanghai\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n[api_auth]\n app_id = \"ytb2bili_extension\" # 应用ID\n app_secret = \"334567890-3456789045678\" # 应用密钥\n cookies_decrypt_key = \"234567804567893456789456789\" # Cookies 解密密钥\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[GeminiConfig]\n enabled = false # 是否启用Gemini服务\n api_key = \"\" # Google AI API密钥(从 https://aistudio.google.com/app/apikey 获取)\n model = \"gemini-2.5-flash\" # 使用的模型(gemini-2.5-flash 快速, gemini-2.5-pro 强大)\n timeout = 120 # 超时时间(秒)\n max_tokens = 8000 # 最大输出token数\n use_for_metadata = false # 是否使用Gemini生成元数据(优先于DeepSeek)\n analyze_video = true # 是否分析视频文件(true=多模态分析,false=仅文本)\n video_sample_frames = 0 # 视频采样帧数(0=上传完整视频)\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n[BilibiliConfig]\n copyright = 2 # 1=自制, 2=转载\n source = \"YouTube\" # 转载来源\n no_reprint = 1 # 0=允许转载, 1=禁止转载\n use_original_title = true # true=使用原视频标题, false=使用AI生成标题\n use_original_desc = false # true=使用原视频描述, false=使用AI生成描述\n custom_title_template = \"\" # 自定义标题模板(可选),支持变量: {original_title}, {ai_title}\n # 示例: \"{original_title}【中文字幕】\" 或 \"【原神MMD】{ai_title}\"\n custom_desc_template = \"\" # 自定义描述模板(可选),支持变量: {original_desc}, {ai_desc}\n \n # 新增配置项\n tid = 122 # 分区ID(122=日常,138=搞笑,详见B站分区列表)\n dynamic = \"发布了新视频!\" # 动态文本\n open_elec = 0 # 是否开启充电面板 0=关闭, 1=开启\n selection_reserve = 0 # 参与活动ID(0表示不参与,暂不被SDK支持)\n up_selection_reply = 0 # 是否展示推荐评论 0=关闭, 1=开启(暂不被SDK支持)\n up_close_reply = 0 # 是否关闭评论 0=开启评论, 1=关闭评论(暂不被SDK支持)\n up_close_reward = 0 # 是否关闭打赏 0=开启, 1=关闭(暂不被SDK支持)\n\n # 自定义描述模板示例:\n # custom_desc_template = \"\"\"\n # 【视频内容】\n # {ai_desc}\n # \n # 【原视频描述】\n # {original_desc}\n # \"\"\"\n"}, "ca2ca636a07c17d0cd3ca59c99790154f70a8bd0": {"t": 1785759473.815877, "n": 2563, "h": "f0f7bc652424c7ae", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"/Users/apple/opt/file_upload/media\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"mysql\"\n host = \"localhost\"\n port = 3306\n username = \"root\"\n password = \"your_password\"\n database = \"bili_up\"\n ssl_mode = \"\"\n timezone = \"Asia/Shanghai\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[GeminiConfig]\n enabled = false # 是否启用Gemini服务\n api_key = \"\" # Google AI API密钥(从 https://aistudio.google.com/app/apikey 获取)\n model = \"gemini-2.5-flash\" # 使用的模型(gemini-2.5-flash 快速, gemini-2.5-pro 强大)\n timeout = 120 # 超时时间(秒)\n max_tokens = 8000 # 最大输出token数\n use_for_metadata = false # 是否使用Gemini生成元数据(优先于DeepSeek)\n analyze_video = true # 是否分析视频文件(true=多模态分析,false=仅文本)\n video_sample_frames = 0 # 视频采样帧数(0=上传完整视频)\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n[BilibiliConfig]\n copyright = 2 # 1=自制, 2=转载\n source = \"YouTube\" # 转载来源\n no_reprint = 1 # 0=允许转载, 1=禁止转载\n use_original_title = true # true=使用原视频标题, false=使用AI生成标题\n use_original_desc = false # true=使用原视频描述, false=使用AI生成描述\n custom_title_template = \"\" # 自定义标题模板(可选),支持变量: {original_title}, {ai_title}\n # 示例: \"{original_title}【中文字幕】\" 或 \"【原神MMD】{ai_title}\"\n custom_desc_template = \"\" # 自定义描述模板(可选),支持变量: {original_desc}, {ai_desc}\n \n # 新增配置项\n tid = 122 # 分区ID(122=日常,138=搞笑,详见B站分区列表)\n dynamic = \"发布了新视频!\" # 动态文本\n open_elec = 0 # 是否开启充电面板 0=关闭, 1=开启\n selection_reserve = 0 # 参与活动ID(0表示不参与,暂不被SDK支持)\n up_selection_reply = 0 # 是否展示推荐评论 0=关闭, 1=开启(暂不被SDK支持)\n up_close_reply = 0 # 是否关闭评论 0=开启评论, 1=关闭评论(暂不被SDK支持)\n up_close_reward = 0 # 是否关闭打赏 0=开启, 1=关闭(暂不被SDK支持)\n\n # 自定义描述模板示例:\n # custom_desc_template = \"\"\"\n # 【视频内容】\n # {ai_desc}\n # \n # 【原视频描述】\n # {original_desc}\n # \"\"\"\n"}, "b6c7986910c09a4c0aca7a9fd19786191d95d5e6": {"t": 1785759475.1727107, "n": 2525, "h": "11c74ac40645ac5d", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"/Users/apple/opt/file_upload/media\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"sqlite\"\n host = \"\"\n port = 0\n username = \"\"\n password = \"\"\n database = \"bili_up.db\"\n ssl_mode = \"\"\n timezone = \"\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[GeminiConfig]\n enabled = false # 是否启用Gemini服务\n api_key = \"\" # Google AI API密钥(从 https://aistudio.google.com/app/apikey 获取)\n model = \"gemini-2.5-flash\" # 使用的模型(gemini-2.5-flash 快速, gemini-2.5-pro 强大)\n timeout = 120 # 超时时间(秒)\n max_tokens = 8000 # 最大输出token数\n use_for_metadata = false # 是否使用Gemini生成元数据(优先于DeepSeek)\n analyze_video = true # 是否分析视频文件(true=多模态分析,false=仅文本)\n video_sample_frames = 0 # 视频采样帧数(0=上传完整视频)\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n[BilibiliConfig]\n copyright = 2 # 1=自制, 2=转载\n source = \"YouTube\" # 转载来源\n no_reprint = 1 # 0=允许转载, 1=禁止转载\n use_original_title = true # true=使用原视频标题, false=使用AI生成标题\n use_original_desc = false # true=使用原视频描述, false=使用AI生成描述\n custom_title_template = \"\" # 自定义标题模板(可选),支持变量: {original_title}, {ai_title}\n # 示例: \"{original_title}【中文字幕】\" 或 \"【原神MMD】{ai_title}\"\n custom_desc_template = \"\" # 自定义描述模板(可选),支持变量: {original_desc}, {ai_desc}\n \n # 新增配置项\n tid = 122 # 分区ID(122=日常,138=搞笑,详见B站分区列表)\n dynamic = \"发布了新视频!\" # 动态文本\n open_elec = 0 # 是否开启充电面板 0=关闭, 1=开启\n selection_reserve = 0 # 参与活动ID(0表示不参与,暂不被SDK支持)\n up_selection_reply = 0 # 是否展示推荐评论 0=关闭, 1=开启(暂不被SDK支持)\n up_close_reply = 0 # 是否关闭评论 0=开启评论, 1=关闭评论(暂不被SDK支持)\n up_close_reward = 0 # 是否关闭打赏 0=开启, 1=关闭(暂不被SDK支持)\n\n # 自定义描述模板示例:\n # custom_desc_template = \"\"\"\n # 【视频内容】\n # {ai_desc}\n # \n # 【原视频描述】\n # {original_desc}\n # \"\"\"\n"}, "6eec853377f1fe0e0cad68556b3a545d54d60f98": {"t": 1785759476.4623215, "n": 1428, "h": "ea6d9c49daee2c8a", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"/Users/apple/opt/file_upload/media\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"sqlite\"\n host = \"\"\n port = 0\n username = \"\"\n password = \"\"\n database = \"bili_up.db\"\n ssl_mode = \"\"\n timezone = \"\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n[BilibiliConfig]\n copyright = 2 # 1=自制, 2=转载\n source = \"YouTube\" # 转载来源\n no_reprint = 1 # 0=允许转载, 1=禁止转载\n use_original_title = true # true=使用原视频标题(推荐), false=使用AI生成标题\n use_original_desc = false # true=使用原视频描述, false=使用AI生成描述(推荐)\n custom_desc_template = \"\" # 自定义描述模板(可选),支持变量: {original_desc}, {ai_desc}\n\n # 自定义描述模板示例:\n # custom_desc_template = \"\"\"\n # 【视频内容】\n # {ai_desc}\n # \n # 【原视频描述】\n # {original_desc}\n # \"\"\"\n"}, "d62a2ba3dadd35abf490b520595b5fbcd1656879": {"t": 1785759477.6916194, "n": 956, "h": "35a4562f5c2cdf86", "c": "# Bilibili 视频上传后端 - 配置文件\n\nlisten = \":8096\"\nenvironment = \"development\"\ndebug = true\nfileUpDir = \"/Users/apple/opt/file_upload/media\"\nyt_dlp_path = \"\"\n\n[database]\n type = \"sqlite\"\n host = \"\"\n port = 0\n username = \"\"\n password = \"\"\n database = \"bili_up.db\"\n ssl_mode = \"\"\n timezone = \"\"\n\n[auth]\n jwt_secret = \"your-jwt-secret-key\"\n jwt_expiration = 24\n session_secret = \"your-session-secret\"\n\n[TenCosConfig]\n Enabled = false\n CosBucketURL = \"\"\n CosSecretId = \"\"\n CosSecretKey = \"\"\n CosRegion = \"\"\n CosBucket = \"\"\n SubAppId = \"\"\n CosUrL = \"\"\n\n[DeepSeekTransConfig]\n enabled = true\n api_key = \"sk-deepseek_api_key\"\n models = \"\"\n endpoint = \"https://api.deepseek.com\"\n timeout = 60\n max_tokens = 4000\n\n[ProxyConfig]\n use_proxy = false\n proxy_host = \"http://127.0.0.1:7890\"\n\n[AnalyticsConfig]\n enabled = false\n server_url = \"http://localhost:8080\"\n api_key = \"\"\n product_id = \"bili-up-api\"\n debug = false\n encryption_key = \"\"\n\n\n\n"}, "fda16eb43cbc635cbe8b3373a87408346f8d62ce": {"t": 1785759480.22444, "n": 2486, "h": "d215cdd583ffca7b", "c": "# Bilibili 视频上传后端 - 配置文件\n\n# ======================\n# 基础配置\n# ======================\nlisten = \":8096\" # HTTP 服务监听端口\nenvironment = \"development\" # 运行环境: development, production\ndebug = true # 是否启用调试模式\nFileUpDir = \"/Users/apple/opt/file_upload/media\" # 文件上传目录(绝对路径)\n\n# ======================\n# 数据库配置\n# ======================\n[database]\n type = \"mysql\" # 数据库类型: mysql, postgres\n host = \"localhost\" # 数据库主机\n port = 3306 # 数据库端口\n username = \"root\" # 数据库用户名\n password = \"Ab123456\" # 数据库密码\n database = \"bili_up\" # 数据库名称\n ssl_mode = \"disable\" # SSL 模式\n timezone = \"Asia/Shanghai\" # 时区\n\n# ======================\n# JWT 认证配置\n# ======================\n[auth]\n jwt_secret = \"your-jwt-secret-key\" # JWT 密钥(生产环境请修改)\n jwt_expiration = 24 # JWT 过期时间(小时)\n session_secret = \"your-session-secret\" # Session 密钥(生产环境请修改)\n\n# ======================\n# 腾讯云 COS 存储配置\n# ======================\n[TenCosConfig]\n enabled = true # 是否启用腾讯云 COS 存储\n CosBucketURL = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\" # COS Bucket URL\n CosSecretId = \"your-secret-id\" # 腾讯云 SecretId\n CosSecretKey = \"your-secret-key\" # 腾讯云 SecretKey\n CosRegion = \"ap-guangzhou\" # COS 地域\n CosBucket = \"your-bucket\" # Bucket 名称\n SubAppId = \"your-appid\" # 子应用ID\n CosUrL = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\" # COS 访问URL\n\n# ======================\n# 数据分析配置\n# ======================\n[AnalyticsConfig]\n enabled = false # 是否启用数据分析\n server_url = \"http://localhost:8080\" # 分析服务器地址\n api_key = \"your-analytics-api-key\" # API密钥\n product_id = \"bili-up-api\" # 产品ID\n debug = false # 是否启用调试模式\n encryption_key = \"\" # AES加密密钥(可选,16/24/32字节)\n # 示例: \"1234567890123456\" (16字节)\n\n# ======================\n# 说明\n# ======================\n# 以下配置已内置在代码中,无需在此配置文件中设置:\n#\n# 1. BaiduTransConfig - 百度翻译服务\n# 2. DeepSeekTransConfig - DeepSeek AI 服务(可通过API动态配置)\n# 3. app_auth - 应用启动认证\n#\n# 详细说明请参考: docs/CONFIG_GUIDE.md\n"}}, "docker/config.toml.example": {"7a76c7b491d563e88aa452b5bc774be26e4fbecd": {"t": 1785746805.365853, "n": 3132, "h": "b24f038303c4cea9", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 预定义登录账号\n# 请自定义的账号/密码\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"admin123\"\n\n\n# 浏览器插件提交必须启用 HMAC 签名验证。请将下列两个密钥替换成各自\n# 随机生成的 32+ 字符值,并在支持签名的插件中配置相同的 app_id/app_secret。\n[api_auth]\nenabled = true\napp_id = \"ytb2bili_extension\"\napp_secret = \"replace-with-a-random-extension-hmac-secret\"\ncookies_decrypt_key = \"replace-with-a-separate-32-byte-cookie-key\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# ==========================================================================\n# 宿主机 Apple Silicon ASR(Docker 通过 host.docker.internal 调用)\n# ==========================================================================\n[asr]\nprovider = \"local_mlx_whisper\"\nfallback_provider = \"\" # 需要 BCut 回退时设置为 \"bcut\"\nbase_url = \"http://host.docker.internal:9000/v1\"\napi_key = \"\"\nmodel = \"mlx-community/whisper-large-v3-turbo\"\nlanguage = \"\"\ntimeout_seconds = 1800\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n\n[tencent_tts]\nsecret_id = \"\" # Tencent Cloud SecretId\nsecret_key = \"\" # Tencent Cloud SecretKey\nregion = \"ap-guangzhou\" # Tencent Cloud region\n"}, "d2e824162a0bdce4a56aebc045fb0ea8123a4b1b": {"t": 1785759466.4097705, "n": 3132, "h": "b24f038303c4cea9", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 预定义登录账号\n# 请自定义的账号/密码\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"admin123\"\n\n\n# 浏览器插件提交必须启用 HMAC 签名验证。请将下列两个密钥替换成各自\n# 随机生成的 32+ 字符值,并在支持签名的插件中配置相同的 app_id/app_secret。\n[api_auth]\nenabled = true\napp_id = \"ytb2bili_extension\"\napp_secret = \"replace-with-a-random-extension-hmac-secret\"\ncookies_decrypt_key = \"replace-with-a-separate-32-byte-cookie-key\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# ==========================================================================\n# 宿主机 Apple Silicon ASR(Docker 通过 host.docker.internal 调用)\n# ==========================================================================\n[asr]\nprovider = \"local_mlx_whisper\"\nfallback_provider = \"\" # 需要 BCut 回退时设置为 \"bcut\"\nbase_url = \"http://host.docker.internal:9000/v1\"\napi_key = \"\"\nmodel = \"mlx-community/whisper-large-v3-turbo\"\nlanguage = \"\"\ntimeout_seconds = 1800\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n\n[tencent_tts]\nsecret_id = \"\" # Tencent Cloud SecretId\nsecret_key = \"\" # Tencent Cloud SecretKey\nregion = \"ap-guangzhou\" # Tencent Cloud region\n"}, "7347c5df85cf7dd5ab482739d9655f041fc74236": {"t": 1785759467.9859817, "n": 2502, "h": "bcf4c0b2594c29cf", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n[auth]\njwt_secret = \"change-this-local-jwt-secret\"\naccess_token_ttl = 7200\nrefresh_token_ttl = 604800\n\n# 预定义登录账号\n# 请自定义的账号/密码\n[[auth.users]]\nemail = \"admin@126.com\"\npassword = \"admin123\"\n\n\n# 不要修改\n[api_auth]\nenabled = false\napp_id = \"ytb2bili_extension\"\napp_secret = \"ytb2bili_secret_2026\"\ncookies_decrypt_key = \"59e7052041ce4bd6aff82f6a0bca9cde\"\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n\n# 水印字体文件路径(可选;用于非会员水印 drawtext fontfile)\nwatermark_font_file = \"/app/fonts/watermark.ttf\"\n\n\n[llm]\nprovider = \"deepseek\" # 服务商: openai, deepseek, ollama, qwen, zhipu, groq, custom\nbase_url = \"https://api.deepseek.com\" # API 端点地址(OpenAI 兼容接口)\napi_key = \"sk-xxxx\"\nmodels = [\"deepseek-v4-flash\", \"deepseek-chat\", \"deepseek-reasoner\"] # 前端可选模型列表\ntemperature = 0.7 # 温度参数 (0.0-2.0)\nmax_tokens = 24096 # 每次请求最大 token 数\ntimeout = 300 # 请求超时(秒)\n\n\n\n\n\n# ============================================================================\n# Azure TTS 语音合成配置(用户自行配置)\n# ============================================================================\n[azure_tts]\nsubscription_key = \"\" # Azure Speech Services 订阅密钥\nregion = \"\" # Azure 区域\n"}, "604caa3e89ce9b417a5370ecbe94e18ee3e931f0": {"t": 1785759470.3413825, "n": 3028, "h": "34bd5e8a31041c5c", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n# Cookies 文件路径(可选,用于下载受限视频)\n# cookies_file = \"/path/to/cookies.txt\"\n\n# 代理地址(可选,用于加速下载)\n# proxy_url = \"http://127.0.0.1:7890\"\n\n# 微软语音服务配置(可选,用于旧版翻译功能)\n# speech_key = \"your_azure_speech_key\"\n# speech_region = \"eastasia\"\n\n# LLM 翻译配置\nllm_translation_enabled = true # 是否启用 LLM 批量翻译(推荐,替代微软翻译)\nllm_translation_batch_size = 25 # 批量翻译每批句子数\nllm_translation_max_workers = 3 # 并发工作者数量\nllm_translation_context_size = 2 # 上下文窗口大小\nllm_translation_source_lang = \"en\" # 源语言代码\nllm_translation_target_lang = \"zh-Hans\" # 目标语言代码\n\n# TTS 字幕音频合成配置\ntts_enabled = false # 是否启用字幕音频合成\n\n# ============================================================================\n# Agent & LLM 配置\n# ============================================================================\n[agent]\nname = \"agent\" # Agent 名称\n\n\n# ============================================================================\n# 自动更新配置\n# ============================================================================\n[updater]\nenabled = true # 是否启用更新检查\nauto_update = false # 是否自动更新(建议设为 false,手动更新更安全)\ncheck_interval = 24 # 检查更新间隔(小时),0 表示禁用\n# update_url = \"https://api.github.com/repos/zolagz/ytb2bili/releases/latest\"\n# current_version = \"0.0.1\"\n\n\n\n# ============================================================================\n# 腾讯云 COS 存储配置(可选,用于云端存储)\n# ============================================================================\n[tencos]\nenabled = false # 是否启用腾讯云 COS 存储\n# cos_bucket_url = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\"\n# cos_secret_id = \"your_secret_id\"\n# cos_secret_key = \"your_secret_key\"\n# cos_region = \"ap-guangzhou\"\n# cos_bucket = \"your-bucket-name\"\n# sub_app_id = \"your_app_id\"\n\n"}, "80694b6b248d350b577abf6cd64b9ca4fef62673": {"t": 1785759472.2285154, "n": 3845, "h": "6ebf65288401551c", "c": "# ytb2bili 配置文件示例(TOML格式)\n# 复制此文件为 config.toml 并根据实际情况修改\n# 注意:环境变量会覆盖此文件中的配置\n\n# ============================================================================\n# 应用基础配置\n# ============================================================================\n\n[server]\nhost = \"0.0.0.0\" # 服务监听地址,0.0.0.0 表示监听所有网卡\nport = 8096 # 服务端口\nstatic_dir = \"./downloads\" # 静态文件目录(视频、字幕等)\nstatic_path = \"/static\" # 静态文件访问路径前缀\n\n\n# ============================================================================\n# 数据库配置\n# ============================================================================\n[database]\ntype = \"mysql\"\nhost = \"mysql\" # Docker Compose 服务名\nport = 3306\nuser = \"ytb2bili\" # 与 docker-compose.yml 一致\npassword = \"ytb2bili@123\"\ndbname = \"bili_up\" # 数据库名(注意是 dbname 不是 database)\nsslmode = \"\" # MySQL 不使用(仅 PostgreSQL 需要)\ntimezone = \"Asia/Shanghai\" # 时区配置\nauto_migrate = true\ntable_prefix = \"\"\n\n\n\n# ============================================================================\n# 视频处理工作流配置\n# ============================================================================\n[workflow]\ndownload_dir = \"./downloads\" # 视频下载目录(必需,应与 server.static_dir 保持一致)\n\n# yt-dlp 可执行文件路径(可选,默认从 PATH 查找)\nytdlp_path = \"/usr/local/bin/yt-dlp\"\n\n# ffmpeg 可执行文件路径(可选,默认从 PATH 查找)\nffmpeg_path = \"/usr/bin/ffmpeg\"\n# Cookies 文件路径(可选,用于下载受限视频)\n# cookies_file = \"/path/to/cookies.txt\"\n\n# 代理地址(可选,用于加速下载)\n# proxy_url = \"http://127.0.0.1:7890\"\n\n# 微软语音服务配置(可选,用于旧版翻译功能)\n# speech_key = \"your_azure_speech_key\"\n# speech_region = \"eastasia\"\n\n# LLM 翻译配置\nllm_translation_enabled = true # 是否启用 LLM 批量翻译(推荐,替代微软翻译)\nllm_translation_batch_size = 25 # 批量翻译每批句子数\nllm_translation_max_workers = 3 # 并发工作者数量\nllm_translation_context_size = 2 # 上下文窗口大小\nllm_translation_source_lang = \"en\" # 源语言代码\nllm_translation_target_lang = \"zh-Hans\" # 目标语言代码\n\n# TTS 字幕音频合成配置\ntts_enabled = false # 是否启用字幕音频合成\n\n# ============================================================================\n# Agent & LLM 配置\n# ============================================================================\n[agent]\nname = \"ytb2bili_agent\" # Agent 名称\n\n[agent.llm]\n# provider = \"openai\" # LLM 提供商: openai, deepseek, openrouter 等\n# api_key = \"sk-proj--\" # LLM API 密钥(必需)\n# model = \"gpt-4\" # 使用的模型名称\n# base_url = \"https://api.openai.com/v1\" # 自定义 API 地址(可选)\n\n# OpenRouter 示例\n# provider = \"openrouter\"\n# api_key = \"sk-or-v1-...\"\n# base_url = \"https://openrouter.ai/api/v1\"\n# model = \"anthropic/claude-3-sonnet\"\n\n# DeepSeek 示例\nprovider = \"deepseek\"\napi_key = \"sk\"\nbase_url = \"https://api.deepseek.com/v1\"\nmodel = \"deepseek-chat\"\n\n# ============================================================================\n# 自动更新配置\n# ============================================================================\n[updater]\nenabled = true # 是否启用更新检查\nauto_update = false # 是否自动更新(建议设为 false,手动更新更安全)\ncheck_interval = 24 # 检查更新间隔(小时),0 表示禁用\n# update_url = \"https://api.github.com/repos/zolagz/ytb2bili/releases/latest\"\n# current_version = \"0.0.1\"\n\n# ============================================================================\n# TTS 服务配置(可选,用于语音合成)\n# ============================================================================\n[tts]\n# base_url = \"https://tts-api.com\"\n# app_id = \"your_app_id\"\n# app_secret = \"your_app_secret\"\n\n# ============================================================================\n# 腾讯云 COS 存储配置(可选,用于云端存储)\n# ============================================================================\n[tencos]\nenabled = false # 是否启用腾讯云 COS 存储\n# cos_bucket_url = \"https://your-bucket.cos.ap-guangzhou.myqcloud.com\"\n# cos_secret_id = \"your_secret_id\"\n# cos_secret_key = \"your_secret_key\"\n# cos_region = \"ap-guangzhou\"\n# cos_bucket = \"your-bucket-name\"\n# sub_app_id = \"your_app_id\"\n\n"}}}}