feat: expose storyforge through public cloud gateway
This commit is contained in:
@@ -132,6 +132,7 @@ N8N_BASE_URL=http://127.0.0.1:5670
|
||||
- `collector-service`:`http://127.0.0.1:8081`
|
||||
- `n8n`:`http://127.0.0.1:5670`
|
||||
- `cli-proxy-api`:`http://127.0.0.1:8317`
|
||||
- 公网入口:`https://test.hyzq.net/storyforge/`
|
||||
|
||||
默认会创建最高权限账号:
|
||||
|
||||
@@ -151,6 +152,11 @@ N8N_BASE_URL=http://127.0.0.1:5670
|
||||
- 触发 `real_cut_pipeline`
|
||||
- 触发 `ai_video_pipeline`
|
||||
- 历史旧运行链已完成移除,当前运行时只保留 StoryForge 自身服务与外部执行引擎
|
||||
- 当前公网接入采用“云服务器 HTTPS 入口 + 本机桥接隧道 + 本机现网执行链”模式:
|
||||
- `https://test.hyzq.net/storyforge/` 由云服务器 `nginx` 提供 HTTPS 入口
|
||||
- `/storyforge/` 静态页反向代理到本机 `Web V4` 静态服务
|
||||
- `/storyforge/v2/*`、`/storyforge/openapi.json`、`/storyforge/healthz` 反向代理到本机 `collector-service`
|
||||
- `cutvideo / huobao / 本机模型 / NAS 录制` 继续由本机和局域网执行链提供
|
||||
|
||||
## 说明
|
||||
|
||||
|
||||
37
deploy/STORYFORGE_TEST_HYZQ_GATEWAY.md
Normal file
37
deploy/STORYFORGE_TEST_HYZQ_GATEWAY.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# StoryForge `test.hyzq.net/storyforge` 公网入口
|
||||
|
||||
当前公网接入不是把执行链整体迁到云服务器,而是:
|
||||
|
||||
1. 云服务器 `nginx` 提供 `https://test.hyzq.net/storyforge/`
|
||||
2. 本机 `collector-service` 继续承接业务与局域网执行引擎
|
||||
3. 本机 `Web V4` 静态服务继续承接前端
|
||||
4. 本机通过 SSH 反向隧道把这两个入口桥接到云服务器
|
||||
|
||||
## 端口映射
|
||||
|
||||
- 云服务器 `127.0.0.1:18181` -> 本机 `127.0.0.1:8081`
|
||||
- 云服务器 `127.0.0.1:18191` -> 本机 `127.0.0.1:3918`
|
||||
|
||||
## 本机常驻服务
|
||||
|
||||
- `com.storyforge.collector`
|
||||
- `com.storyforge.web-v4`
|
||||
- `com.storyforge.cloud-bridge`
|
||||
|
||||
## 云服务器 `nginx` 路由
|
||||
|
||||
- `/storyforge/` -> `127.0.0.1:18191`
|
||||
- `/storyforge/v2/*` -> `127.0.0.1:18181`
|
||||
- `/storyforge/openapi.json` -> `127.0.0.1:18181/openapi.json`
|
||||
- `/storyforge/healthz` -> `127.0.0.1:18181/healthz`
|
||||
|
||||
## 当前优点
|
||||
|
||||
- 不需要把 `cutvideo / huobao / NAS live-recorder / 本机模型` 全部搬上云
|
||||
- 公网入口统一
|
||||
- 本机现网能力不需要改造即可对外开放
|
||||
|
||||
## 当前限制
|
||||
|
||||
- 本机桥接断开时,公网入口不可用
|
||||
- 这是公网 staging / 私有运营入口,更接近“公网可访问的现网桥接”,不是最终完全云原生部署
|
||||
40
deploy/com.storyforge.cloud-bridge.plist.example
Normal file
40
deploy/com.storyforge.cloud-bridge.plist.example
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.storyforge.cloud-bridge</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/bin/ssh</string>
|
||||
<string>-N</string>
|
||||
<string>-i</string>
|
||||
<string>/Users/kris/.ssh/id_ed25519_kylin188</string>
|
||||
<string>-o</string>
|
||||
<string>BatchMode=yes</string>
|
||||
<string>-o</string>
|
||||
<string>ExitOnForwardFailure=yes</string>
|
||||
<string>-o</string>
|
||||
<string>ServerAliveInterval=30</string>
|
||||
<string>-o</string>
|
||||
<string>ServerAliveCountMax=3</string>
|
||||
<string>-o</string>
|
||||
<string>StrictHostKeyChecking=no</string>
|
||||
<string>-o</string>
|
||||
<string>UserKnownHostsFile=/Users/kris/.ssh/known_hosts</string>
|
||||
<string>-R</string>
|
||||
<string>127.0.0.1:18181:127.0.0.1:8081</string>
|
||||
<string>-R</string>
|
||||
<string>127.0.0.1:18191:127.0.0.1:3918</string>
|
||||
<string>ubuntu@111.231.132.51</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/kris/code/StoryForge/data/collector/cloud-bridge.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/kris/code/StoryForge/data/collector/cloud-bridge.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
29
deploy/com.storyforge.web-v4.plist.example
Normal file
29
deploy/com.storyforge.web-v4.plist.example
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.storyforge.web-v4</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/bin/python3</string>
|
||||
<string>-m</string>
|
||||
<string>http.server</string>
|
||||
<string>3918</string>
|
||||
<string>--bind</string>
|
||||
<string>127.0.0.1</string>
|
||||
<string>--directory</string>
|
||||
<string>/Users/kris/code/StoryForge/web/storyforge-web-v4</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/kris/code/StoryForge/web/storyforge-web-v4</string>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/kris/code/StoryForge/data/collector/web-v4.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/kris/code/StoryForge/data/collector/web-v4.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
101
deploy/storyforge-test-hyzq-nginx.conf.fragment
Normal file
101
deploy/storyforge-test-hyzq-nginx.conf.fragment
Normal file
@@ -0,0 +1,101 @@
|
||||
location = /storyforge {
|
||||
auth_basic off;
|
||||
return 301 /storyforge/;
|
||||
}
|
||||
|
||||
location = /storyforge/healthz {
|
||||
auth_basic off;
|
||||
proxy_pass http://127.0.0.1:18181/healthz;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location = /storyforge/openapi.json {
|
||||
auth_basic off;
|
||||
proxy_pass http://127.0.0.1:18181/openapi.json;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location = /storyforge/api/v1/app/update/latest {
|
||||
auth_basic off;
|
||||
proxy_pass http://127.0.0.1:18181/api/v1/app/update/latest;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
location ^~ /storyforge/downloads/ {
|
||||
auth_basic off;
|
||||
proxy_pass http://127.0.0.1:18181/downloads/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
location ^~ /storyforge/v2/ {
|
||||
auth_basic off;
|
||||
proxy_pass http://127.0.0.1:18181/v2/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location ^~ /storyforge/docs {
|
||||
auth_basic off;
|
||||
rewrite ^/storyforge(/docs.*)$ $1 break;
|
||||
proxy_pass http://127.0.0.1:18181;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location ^~ /storyforge/redoc {
|
||||
auth_basic off;
|
||||
rewrite ^/storyforge(/redoc.*)$ $1 break;
|
||||
proxy_pass http://127.0.0.1:18181;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location ^~ /storyforge/ {
|
||||
auth_basic off;
|
||||
rewrite ^/storyforge/?(.*)$ /$1 break;
|
||||
proxy_pass http://127.0.0.1:18191;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
- 目录已经从 `output/ui/` 原型区独立出来,并接上了第一层真实业务接口
|
||||
- 这里面向国内平台的 Web 承载,当前覆盖 `douyin`、`xiaohongshu`、`bilibili`、`kuaishou`、`wechat_video`
|
||||
- `YouTube` 目前明确不在本轮范围内
|
||||
- 已支持通过 `https://test.hyzq.net/storyforge/` 做公网访问
|
||||
- 通用的项目、内容源、复盘、集成等流程可以正常使用
|
||||
- 平台工作台和运行时数据目前只有 `douyin` 做到了完整实现,其余平台统一按 `待接入工作台` 处理
|
||||
- 当前保留的核心页面结构:
|
||||
@@ -99,6 +100,14 @@ python3 -m http.server 3918
|
||||
|
||||
- `http://127.0.0.1:8081`
|
||||
|
||||
如果页面部署在:
|
||||
|
||||
- `https://test.hyzq.net/storyforge/`
|
||||
|
||||
前端会自动把默认后端切到同源的:
|
||||
|
||||
- `https://test.hyzq.net/storyforge`
|
||||
|
||||
## 后续建议
|
||||
|
||||
- 继续补多平台各自更深的专属采集与解析能力,而不只是一套统一抽象层
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
const STORAGE_KEY = "storyforge-web-v4-session";
|
||||
const DEFAULT_BACKEND_URL = "http://127.0.0.1:8081";
|
||||
|
||||
function detectDefaultBackendUrl() {
|
||||
if (typeof window === "undefined") {
|
||||
return "http://127.0.0.1:8081";
|
||||
}
|
||||
const { origin, hostname, port, pathname } = window.location;
|
||||
if (/^https?:/i.test(origin) && pathname.startsWith("/storyforge")) {
|
||||
return `${origin}/storyforge`;
|
||||
}
|
||||
if ((hostname === "127.0.0.1" || hostname === "localhost") && port && port !== "8081") {
|
||||
return "http://127.0.0.1:8081";
|
||||
}
|
||||
return "http://127.0.0.1:8081";
|
||||
}
|
||||
|
||||
const DEFAULT_BACKEND_URL = detectDefaultBackendUrl();
|
||||
|
||||
const navButtons = document.querySelectorAll("[data-screen-target]");
|
||||
const screens = Array.from(document.querySelectorAll("[data-screen]"));
|
||||
|
||||
Reference in New Issue
Block a user