--- title: test colorFrom: purple colorTo: gray sdk: docker app_port: 8890 emoji: 🚀 --- # OpenAI兼容的Sora API服务 这是一个为Sora提供OpenAI兼容接口的API服务。该服务使用cloudscraper绕过Cloudflare验证,支持多key轮询、并发处理和标准的OpenAI接口格式。 ## 功能特点 - **OpenAI兼容接口**:完全兼容OpenAI的`/v1/chat/completions`接口 - **CF验证绕过**:使用cloudscraper库成功绕过Cloudflare验证 - **多key轮询**:支持多个Sora认证token,根据权重和速率限制智能选择 - **并发处理**:支持多个并发请求 - **流式响应**:支持SSE格式的流式响应 - **图像处理**:支持文本到图像生成和图像到图像生成(Remix) - **异步处理**:支持异步生成图像,返回立即响应,防止请求超时 - **状态查询**:提供API端点查询异步任务的状态和结果 - **优化性能**:经过代码优化,提高请求处理速度和资源利用率 - **健康检查**:支持容器健康检查功能 ## 环境要求 - Python 3.8+ - FastAPI 0.95.0+ - cloudscraper 1.2.71+ - 其他依赖见requirements.txt ## 快速部署指南 你可以直接运行不指定任何环境变量,所有环境变量都可以在面板里面配置 管理员登录密钥默认:sk-123456 api请求密钥不设置默认和管理员登录密钥相同 docker 一键运行 ```bash docker run -d -p 8890:8890 --name sora-api 1hei1/sora-api:latest ``` ### 方法一:直接运行 1. 克隆仓库 ```bash git clone https://github.com/1hei1/sora-api.git cd sora-api ``` 2. 安装依赖 ```bash pip install -r requirements.txt ``` 3. 配置API Keys(两种方式) - **方式1**: 创建api_keys.json文件 ```json [ {"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60} ] ``` - **方式2**: 设置环境变量 ```bash # Linux/macOS export API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60}]'  # Windows (PowerShell) $env:API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60}]' # Windows (CMD) set API_KEYS=[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60}]  ``` 4. 配置代理(可选,如果需要) ```bash # Linux/macOS - 基本代理 export PROXY_HOST=127.0.0.1 export PROXY_PORT=7890 # Linux/macOS - 带认证的代理 export PROXY_HOST=127.0.0.1 export PROXY_PORT=7890 export PROXY_USER=username export PROXY_PASS=password # Windows (PowerShell) - 基本代理 $env:PROXY_HOST="127.0.0.1" $env:PROXY_PORT="7890" # Windows (PowerShell) - 带认证的代理 $env:PROXY_HOST="127.0.0.1" $env:PROXY_PORT="7890" $env:PROXY_USER="username" $env:PROXY_PASS="password" # Windows (CMD) - 基本代理 set PROXY_HOST=127.0.0.1 set PROXY_PORT=7890 # Windows (CMD) - 带认证的代理 set PROXY_HOST=127.0.0.1 set PROXY_PORT=7890 set PROXY_USER=username set PROXY_PASS=password ``` 5. 启动服务 ```bash python run.py ``` 6. 访问服务 - API服务地址: http://localhost:8890 - 后台管理面板: http://localhost:8890/admin ### 方法二:Docker部署 1. 构建Docker镜像 ```bash docker build -t sora-api . ``` 2. 运行Docker容器(不同配置选项) **基本运行方式**: ```bash docker run -d -p 8890:8890 --name sora-api sora-api ``` **使用预打包镜像**: ```bash docker run -d -p 8890:8890 --name sora-api 1hei1/sora-api:latest ``` **使用预打包镜像并配置API密钥**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60}]' \ --name sora-api \ 1hei1/sora-api:v0.1 ``` **使用预打包镜像并配置代理**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}]' \ -e PROXY_HOST=host.docker.internal \ -e PROXY_PORT=7890 \ --name sora-api \ 1hei1/sora-api:v0.1 ``` **带API密钥配置**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}, {"key": "Bearer your-sora-token-2", "weight": 2, "max_rpm": 60}]' \ --name sora-api \ sora-api ``` **带基本代理配置**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}]' \ -e PROXY_HOST=host.docker.internal \ -e PROXY_PORT=7890 \ --name sora-api \ sora-api ``` **带认证代理配置**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}]' \ -e PROXY_HOST=host.docker.internal \ -e PROXY_PORT=7890 \ -e PROXY_USER=username \ -e PROXY_PASS=password \ --name sora-api \ sora-api ``` **使用外部配置文件**: ```bash # 首先确保api_keys.json文件已正确配置 docker run -d -p 8890:8890 \ -v $(pwd)/api_keys.json:/app/api_keys.json \ -e PROXY_HOST=host.docker.internal \ -e PROXY_PORT=7890 \ --name sora-api \ sora-api ``` **挂载本地目录保存图片**: ```bash docker run -d -p 8890:8890 \ -v /your/local/path:/app/src/static/images \ --name sora-api \ sora-api ``` **启用详细日志**: ```bash docker run -d -p 8890:8890 \ -e API_KEYS='[{"key": "Bearer your-sora-token-1", "weight": 1, "max_rpm": 60}]' \ -e VERBOSE_LOGGING=true \ --name sora-api \ sora-api ``` **注意**: 在Docker中使用宿主机代理时,请使用`host.docker.internal`而不是`127.0.0.1`作为代理主机地址。 3. 检查容器状态 ```bash docker ps docker logs sora-api ``` 4. 停止和移除容器 ```bash docker stop sora-api docker rm sora-api ``` ## 环境变量说明 | 环境变量 | 描述 | 默认值 | 示例 | |---------|------|--------|------| | `API_HOST` | API服务监听地址 | `0.0.0.0` | `127.0.0.1` | | `API_PORT` | API服务端口 | `8890` | `9000` | | `BASE_URL` | API基础URL(生成图片的时候需要用到) | `http://0.0.0.0:8890` | `https://api.example.com` |  | `PROXY_HOST` | HTTP代理主机 | 空(不使用代理) | `127.0.0.1` | | `PROXY_PORT` | HTTP代理端口 | 空(不使用代理) | `7890` | | `PROXY_USER` | HTTP代理用户名 | 空(不使用认证) | `username` | | `PROXY_PASS` | HTTP代理密码 | 空(不使用认证) | `password` | | `IMAGE_SAVE_DIR` | 图片保存目录 | `src/static/images` | `/data/images` | | `IMAGE_LOCALIZATION` | 是否启用图片本地化 | `False` | `True` | | `ADMIN_KEY` | 管理员API密钥(登录界面输入的密码) | `sk-123456` | `sk-youradminkey` | | `API_AUTH_TOKEN` | API认证令牌(使用api服务传入的key) | 空 | `your-auth-token` | | `VERBOSE_LOGGING` | 是否启用详细日志 | `False` | `True` | ## API密钥配置说明 API密钥配置采用JSON格式,每个密钥包含以下属性: - `key`: Sora认证令牌(必须包含Bearer前缀) - `weight`: 轮询权重,数字越大被选中概率越高 - `max_rpm`: 每分钟最大请求数(速率限制) 示例: ```json [ { "key": "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9...", "weight": 1, "max_rpm": 60 }, { "key": "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9...", "weight": 2, "max_rpm": 60 } ] ``` ## 使用示例 ### 使用curl发送请求 ```bash # 文本到图像请求(非流式) curl -X POST http://localhost:8890/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-api-key" \ -d '{ "model": "sora-1.0", "messages": [ {"role": "user", "content": "生成一只在草地上奔跑的金毛犬"} ], "n": 1, "stream": false }' # 文本到图像请求(流式) curl -X POST http://localhost:8890/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer your-api-key" \ -d '{ "model": "sora-1.0", "messages": [ {"role": "user", "content": "生成一只在草地上奔跑的金毛犬"} ], "n": 1, "stream": true }' # 查询异步任务状态 curl -X GET http://localhost:8890/v1/generation/chatcmpl-123456789abcdef \ -H "Authorization: Bearer your-api-key" ``` ## 常见问题排查 1. **连接超时或无法连接** - 检查代理配置是否正确 - 如使用代理认证,确认用户名密码正确 - 确认Sora服务器是否可用 - 检查本地网络连接 2. **API密钥加载失败** - 确认api_keys.json格式正确 - 检查环境变量API_KEYS是否正确设置 - 查看日志中的错误信息 3. **图片生成失败** - 确认Sora令牌有效性 - 查看日志中的错误信息 - 检查是否超出账户额度限制 4. **Docker容器启动失败** - 检查端口是否被占用 - 确认环境变量设置正确 - 查看Docker日志中的错误信息 5. **环境变量API_AUTH_TOKEN和ADMIN_KEY的区别** - 环境变量 API_AUTH_TOKEN代表你在cheery studio 或者newapi里调用填写的令牌 - 环境变量 ADMIN_KEY 代表你管理面板的登录密码 - 当不设置API_AUTH_TOKE时 其值默认等于ADMIN_KEY的值 6. **环境变量BASE_URL的作用** - 这个是图片本地化时设置的,比如生成了一张图片,获取到图片原始url,由于有的客户端不能访问sora,所以要本地化,这个base_url就是指定本地化图片的url前缀。 6. **token无效** - 首次使用的token需要设置用户名,可以使用下面的脚本批量设置用户名: ```python import random import string import logging import cloudscraper # Configure logging tlogging = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") # --- Configuration --- PROXY = { "http": "http://127.0.0.1:7890", "https": "http://127.0.0.1:7890" } PROFILE_API = "https://sora.chatgpt.com/backend/me" TOKENS_FILE = "tokens.txt" # 每行一个 Bearer token RESULTS_FILE = "update_results.txt" # 保存更新结果 USERNAME_LENGTH = 8 # 随机用户名长度 # --- Utilities --- def random_username(length: int = USERNAME_LENGTH) -> str: """生成全小写随机用户名""" return ''.join(random.choices(string.ascii_lowercase, k=length)) def sanitize_headers(headers: dict) -> dict: """ 移除所有非 Latin-1 字符,确保 headers 可以被底层 HTTP 库正确编码。 """ new = {} for k, v in headers.items(): if isinstance(v, str): new[k] = v.encode('latin-1', 'ignore').decode('latin-1') else: new[k] = v return new class SoraBatchUpdater: def __init__(self, proxy: dict = None): self.proxy = proxy or {} def update_username_for_token(self, token: str) -> tuple[bool, str]: """ 针对单个 Bearer token,生成随机用户名并发送更新请求。 返回 (success, message)。 """ scraper = cloudscraper.create_scraper() if self.proxy: scraper.proxies = self.proxy headers = { "Accept": "*/*", "Accept-Language": "zh-CN,zh;q=0.9", "Content-Type": "application/json", "Authorization": f"Bearer {token}", "sec-ch-ua": '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", } headers = sanitize_headers(headers) new_username = random_username() payload = {"username": new_username} try: resp = scraper.post( PROFILE_API, headers=headers, json=payload, allow_redirects=False, timeout=15 ) status = resp.status_code if resp.ok: msg = f"OK ({new_username})" logging.info("Token %s: updated to %s", token[:6], new_username) return True, msg else: text = resp.text.replace('\n', '') msg = f"Failed {status}: {text}" # 简要错误信息 logging.warning("Token %s: %s", token[:6], msg) return False, msg except Exception as e: msg = str(e) logging.error("Token %s exception: %s", token[:6], msg) return False, msg def batch_update(self, tokens: list[str]) -> None: """ 对一组 Bearer token 批量更新用户名,并将结果写入 RESULTS_FILE。 """ results = [] for token in tokens: success, message = self.update_username_for_token(token) results.append((token, success, message)) # 写入结果文件 with open(RESULTS_FILE, 'w', encoding='utf-8') as f: for token, success, msg in results: status = 'SUCCESS' if success else 'ERROR' f.write(f"{token} ---- {status} ---- {msg}\n") logging.info("Batch update complete. Results saved to %s", RESULTS_FILE) def load_tokens(filepath: str) -> list[str]: """从文件加载每行一个 token 的列表""" try: with open(filepath, 'r', encoding='utf-8') as f: return [line.strip() for line in f if line.strip()] except FileNotFoundError: logging.error("Tokens file not found: %s", filepath) return [] if __name__ == '__main__': tokens = load_tokens(TOKENS_FILE) if not tokens: logging.error("No tokens to update. Exiting.") else: updater = SoraBatchUpdater(proxy=PROXY) updater.batch_update(tokens) ``` ## 性能优化 最新版本包含以下性能优化: 1. **代码重构**:简化了代码结构,提高可读性和可维护性 2. **内存优化**:减少不必要的内存使用,优化大型图像处理 3. **异步处理**:全面使用异步处理提高并发性能 4. **错误处理**:改进了错误处理和日志记录 5. **密钥管理**:优化了密钥轮询算法,提高了可靠性 6. **容器优化**:增强了Docker容器配置,支持健康检查 ## 贡献 欢迎提交问题报告和改进建议! ## 许可证 MIT