doubao2api

wangchuxiaoji-ossApache-2.0更新放缓

把豆包逆向成 OpenAI 兼容接口,免费提供多模态对话、图像/视频/音乐生成和文件托管,方便接入 AI Agent。

Reverse-engineered Doubao (豆包) API → OpenAI-compatible REST service. Free multimodal chat, image/video/music generation, and file hosting for AI agents.

v0.1.0发布于 2026-05-21 23:19 UTC312star88fork同步于 2026-11-07 07:30 UTC

怎么上手

由 README 提炼,执行前请确认
pip install git+https://github.com/wangchuxiaoji-oss/doubao2api.git
playwright install chromium
python -m doubao2api
硬件要求按 README 说明

README 未说明显存或 GPU 要求;服务端依赖 Playwright 驱动的 Chromium 浏览器完成登录与请求,可跑在普通 CPU 服务器上。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

逆向豆包客户端 API,转成 OpenAI 兼容接口,给纯文本 Agent 补上识图、读文件和多媒体生成能力

把豆包逆向成 OpenAI 兼容接口,免费提供多模态对话、图像/视频/音乐生成和文件托管,方便接入 AI Agent。

核心能力

  • 提供 OpenAI 兼容的 /v1/chat/completions 等端点
  • 支持快速/思考/专家三档模式并提取思维链
  • 识图并读取 PDF、Word、Excel 等 60+ 种文件格式
  • 免费生成图片、视频和音乐
  • 通过 /v1/files 上传最大 1GB 文件换取永久 TOS URI

容易踩的坑

需先通过 QR 扫码或 Admin 面板登录豆包账号拿到 session,否则接口不可用;服务依赖 Playwright 及 Chromium,要额外执行 playwright install chromium;默认监听 0.0.0.0:9090 且不设 DOUBAO_API_KEY 时无认证,暴露公网前务必配置;豆包模型不支持 Function Calling,不适合作为编程智能体后端。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

1 个版本v0.1.0
  1. v0.1.0v0.1.0 - 首个正式版本最新正式版2026-05-21 · 2026-05-21 23:19 UTC

    doubao2api v0.1.0

    逆向豆包客户端 API,为 AI 智能体提供免费多模态能力。

    功能

    • 多模态对话:多轮对话、深度思考(思维链)、联网搜索
    • 多模态理解:识图、读 PDF/Word/Excel/代码等 60+ 种文件格式
    • 图片生成:文生图、图生图
    • 视频生成:Seedance 2.0(异步任务)
    • 音乐生成:文本描述 + 可选歌词
    • 文件上传:最大 1GB,永久 TOS URI,可做文件中转站
    • OpenAI 兼容:标准 /v1/ 接口,可直接对接现有 Agent 框架
    • QR 扫码登录:全平台,无需桌面客户端

    安装

    pip install git+https://github.com/wangchuxiaoji-oss/doubao2api.git
    

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    doubao2api

    Python 3.10+ License Docker GitHub Stars GitHub Forks GitHub Issues GitHub Last Commit

    逆向豆包(Doubao)客户端 API,为 AI 智能体提供免费的多模态能力。通过 OpenAI 兼容接口,让任何纯文本模型也能识图、读文件、生成图片/音乐/视频。

    起初只是想给自己的 Hermes Agent(基于 DeepSeek V4 Flash)补上识图能力,结果越写越多,索性做成了完整的逆向客户端和 API 服务。

    目录

    这个项目能做什么

    本项目适合为通用 AI 智能体(如 OpenClaw、Hermes 等对话/任务型 Agent)补全多模态能力。

    举个实际例子:我的 Hermes Agent 接入的是 DeepSeek V4 Flash——一个纯文本模型,看不了图、读不了文件、更不能生成多媒体内容。接入 doubao2api 之后,相当于给它装上了"眼睛"和"手":

    • 多模态对话:多轮对话、深度思考(思维链)、联网搜索,完整的 ChatCompletion 能力
    • 多模态理解:识图、读 PDF/Word/Excel/代码等 60+ 种文件格式,纯文本模型也能"看懂"图片和文档
    • 多媒体生成:免费生成图片(文生图、图生图)、音乐、视频,Agent 的输出不再局限于文字
    • 文件中转站(奇淫技巧):通过 /v1/files 可上传任意文件(最大 1GB)获得一个永久 TOS URI,之后随时凭这个 URI 调用 /v1/files/download 换取 7 天有效的下载链接,过期了再换一个就行。这意味着你可以把它当作免费的跨机器文件传输通道——Agent A 在服务器 A 上传文件拿到 URI,把 URI 传给 Agent B,Agent B 在另一台服务器上凭 URI 获取下载链接直接拉取文件。无需自建 OSS,无需打通内网,单文件最大 1GB,存储不过期。有兴趣的兄弟可以基于这个开做个文件中转,感觉会很不错

    ⚠️ 不适合编程智能体:豆包客户端模型不支持 Function Calling / Tool Use(无法调用外部工具如文件读写、终端命令、代码搜索等),因此不适合作为编程智能体(Claude Code、Codex、OpenCode 等)的后端模型。如果你需要的是能操作代码仓库的 coding agent,请选择原生支持工具调用的模型 API。

    原理

    通过 QR 扫码登录(全平台)获取 sessionid 等认证 Cookie,然后调用豆包内部 SSE 流式端点实现对话、图片/视频/音乐生成。

    端点协议思考链状态
    POST /samantha/chat/completionJSON 明文 sentEvent有 — block_type=10040 + 10000✅ 推荐主用
    POST /alice/message/stream_call_botbase64 编码 payload无旧端点,已废弃
    • 认证: Cookie (sessionid, ttwid, passport_csrf_token)
    • 响应: Server-Sent Events 流

    快速开始

    安装

    # 方式一:pip 安装(推荐)
    pip install git+https://github.com/wangchuxiaoji-oss/doubao2api.git
    
    # 方式二:从源码
    git clone https://github.com/wangchuxiaoji-oss/doubao2api.git
    cd doubao2api
    pip install -e .
    

    Docker 部署(可选)

    docker build -t doubao2api .
    docker run -d -p 9090:9090 -v ./. doubao_session.json:/app/.doubao_session.json doubao2api
    

    前置条件

    1. Python 3.10+
    2. 已安装依赖(pip install 会自动处理)

    QR 扫码登录(推荐,跨平台)

    不需要安装豆包桌面客户端:

    from doubao2api.qr_login import QRLogin
    
    result = QRLogin.login_and_save(".doubao_session.json")
    

    从 Session 文件创建客户端

    import asyncio
    from doubao2api import DoubaoChatClient
    
    async def main():
        client = DoubaoChatClient.from_session()
        async with client:
            result = await client.chat("你好,请介绍一下你自己")
            print(result.text)
    
    asyncio.run(main())
    

    流式输出

    async with DoubaoChatClient.from_session() as client:
        async for msg in client.chat_stream("讲个笑话"):
            if msg.is_text_chunk:
                print(msg.text, end="", flush=True)
    

    三模式对话(快速/思考/专家)

    from doubao2api import DoubaoChatClient, EXTENSION_BOT_ID
    
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        # 快速模式 (need_deep_think=0)
        result = await client.chat_completion("1+1=?")
    
        # 思考模式 (need_deep_think=1) — 带思维链
        result = await client.chat_completion("解释量子纠缠", need_deep_think=1)
        print(f"思考: {result.thinking_text}")
        print(f"回答: {result.text}")
    
        # 专家模式 (need_deep_think=3) — 深度推理
        result = await client.chat_completion("证明勾股定理", need_deep_think=3)
    

    图片上传 + 多模态对话

    from doubao2api import DoubaoChatClient, EXTENSION_BOT_ID
    
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        image_bytes = open("photo.png", "rb").read()
        att = await client.upload_image(image_bytes, "photo.png")
        result = await client.chat_completion(
            text="描述这张图片的内容",
            image_attachments=[att],
            need_deep_think=0,
        )
    

    注意: 图片功能需要使用 EXTENSION_BOT_ID(7338286299411103781)。

    通过 REST API 上传大图片(推荐,无需 base64):

    # 先上传图片,获取 CDN URL
    curl -F "[email protected]" http://localhost:9090/v1/images/upload
    # -> {"url": "https://...", "key": "tos-cn-i-.../xxx.png", ...}
    
    # 然后在聊天中直接引用 URL
    curl http://localhost:9090/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{"model":"doubao-expert","messages":[{"role":"user","content":[
        {"type":"text","text":"这是什么?"},
        {"type":"image_url","image_url":{"url":"上一步返回的url"}}
      ]}],"stream":true}'
    

    文件上传 + 文档对话

    支持 PDF、TXT、DOCX、XLSX、PPTX、CSV、Markdown、代码文件等 60+ 种格式。

    from doubao2api import DoubaoChatClient, UploadedFile, EXTENSION_BOT_ID
    
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        # 上传文件
        file_bytes = open("report.pdf", "rb").read()
        uploaded = await client.upload_file(file_bytes, "report.pdf")
        # uploaded: UploadedFile(uri='tos-cn-i-ik7evvg4ik/xxx.pdf', name='report.pdf', size=102400, file_type='pdf')
    
        # 带文件引用的对话
        result = await client.chat_completion(
            text="总结这份文档的要点",
            file_attachments=[uploaded],
        )
        print(result.text)
    
    多文件上传
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        # 同时上传多个文件
        files = []
        for path in ["data.csv", "readme.md", "config.json"]:
            data = open(path, "rb").read()
            uploaded = await client.upload_file(data, path)
            files.append(uploaded)
    
        # 一次对话引用多个文件
        result = await client.chat_completion(
            text="对比这三个文件的内容,找出关键差异",
            file_attachments=files,
        )
    
    文件 + 图片混合
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        # 同时附带文件和图片
        img_att = await client.upload_image(open("chart.png", "rb").read(), "chart.png")
        file_att = await client.upload_file(open("data.csv", "rb").read(), "data.csv")
    
        result = await client.chat_completion(
            text="图表和数据是否一致?",
            image_attachments=[img_att],
            file_attachments=[file_att],
        )
    
    流式输出 + 文件
    async with DoubaoChatClient.from_session(bot_id=EXTENSION_BOT_ID) as client:
        uploaded = await client.upload_file(open("paper.pdf", "rb").read(), "paper.pdf")
    
        async for chunk in client.chat_stream_completion(
            text="逐段翻译这篇论文",
            file_attachments=[uploaded],
            need_deep_think=1,  # 思考模式
        ):
            if chunk.thinking:
                print(f"[思考] {chunk.thinking}", end="")
            if chunk.text:
                print(chunk.text, end="", flush=True)
    
    UploadedFile 数据结构
    @dataclass
    class UploadedFile:
        uri: str = ""        # TOS 存储路径,如 "tos-cn-i-ik7evvg4ik/xxx.pdf"
        name: str = ""       # 原始文件名
        size: int = 0        # 文件大小(字节)
        file_type: str = ""  # 文件扩展名(不含点号)
    
    上传流程详解

    upload_file() 内部自动完成以下 4 步:

    ┌─────────────────────────────────────────────────────────────────────┐
    │ Step 1: POST /alice/resource/prepare_upload                         │
    │   请求: {"tenant_id":"5","scene_id":"5","resource_type":1}          │
    │   响应: service_id, upload_auth_token (AK/SK/SessionToken)          │
    ├─────────────────────────────────────────────────────────────────────┤
    │ Step 2: GET /top/v1?Action=ApplyImageUpload&ServiceId=xxx           │
    │   签名: AWS Signature V4 (使用 Step 1 的 STS 凭证)                  │
    │   响应: StoreUri, UploadHosts, Auth (TOS token), SessionKey         │
    ├─────────────────────────────────────────────────────────────────────┤
    │ Step 3: POST https://{tos_host}/upload/v1/{store_uri}               │
    │   Headers: Authorization={TOS Auth}, Content-CRC32={crc32_hex}      │
    │   Body: 文件二进制内容                                               │
    │   响应: {"code":2000,"message":"Success","data":{"crc32":"xxx"}}    │
    ├─────────────────────────────────────────────────────────────────────┤
    │ Step 4: POST /top/v1?Action=CommitImageUpload&ServiceId=xxx         │
    │   签名: AWS Signature V4                                            │
    │   请求: {"SessionKey":"..."}                                        │
    │   响应: UriStatus=2000 (成功)                                       │
    └─────────────────────────────────────────────────────────────────────┘
    

    关键技术点:

    • /top/v1 是豆包对 ByteDance ImageX API 的反向代理,避免了直接调用 imagex.volcengineapi.com 的 PSM 条件限制
    • 签名使用标准 AWS Signature V4 算法(region=cn-north-1, service=imagex)
    • TOS 上传需要 Content-CRC32 header(小写 hex,8 位)
    • STS 凭证有效期约 1 小时,每次上传重新获取
    支持的文件格式完整列表
    类别扩展名
    文档pdf, txt, csv, docx, doc, xlsx, xls, pptx, ppt, md, mobi, epub
    Web/标记html, css, xml, json, yaml, yml
    Pythonpy
    JavaScript/TypeScriptjs, ts, tsx, jsx
    Java/Kotlinjava, kt
    C/C++c, cpp, h, hpp
    Gogo, mod, sum
    Rustrs
    Swiftswift
    C#cs, xaml
    Rubyrb
    PHPphp
    Perlpl
    Shellsh, bash, bat, cmd, ps1
    Lualua
    Dartdart
    Scalascala
    Vuevue
    Protocol Buffersproto
    Dockerdockerfile
    配置env, ini, toml, plist, feature, vbs, vmx, vbox
    图片png, jpeg, jpg, webp
    文件大小限制
    • 单文件最大约 50MB(受 TOS 单次上传限制)
    • 超大文件建议分片或使用 URL 引用方式
    在 chat/completion 中引用文件的 content_block 结构

    文件在消息中以 block_type=10052 的 attachment block 传递,attachment type=3 表示文件:

    {
      "block_type": 10052,
      "content": {
        "attachment_block": {
          "attachments": [{
            "type": 3,
            "identifier": "uuid",
            "file": {
              "uri": "tos-cn-i-ik7evvg4ik/xxx.pdf",
              "url": "",
              "file_type": 0,
              "name": "report.pdf",
              "size": 102400
            },
            "parse_state": 1,
            "review_state": 1,
            "upload_status": 1,
            "progress": 100,
            "src": ""
          }]
        },
        "pc_event_block": ""
      },
      "block_id": "uuid",
      "parent_id": "",
      "meta_info": [],
      "append_fields": []
    }
    

    attachment type 枚举:

    type含义
    1图片
    3文件(PDF/TXT/代码等)

    图片生成(文生图)

    async with DoubaoChatClient.from_session() as client:
        result = await client.generate_image(
            prompt="一只柴犬在樱花树下",
            ratio="16:9",  # 支持 "1:1", "16:9", "9:16"
        )
        for img in result.images:
            print(f"下载: {img.ori_url}")
    

    水印限制: 所有 API 返回的图片 URL 均带有水印(CDN 层面通过 ImageX tplv 模板渲染),无法绕过。

    视频生成(文生视频)

    使用 Seedance 2.0 全能视频模型,每日约 10 次免费额度。

    async with DoubaoChatClient.from_session() as client:
        result = await client.generate_video(
            prompt="一只柴犬在雪地里奔跑",
            ratio="16:9",
            timeout=300,
        )
        for v in result.videos:
            print(f"视频: {v.video_url}")
            print(f"时长: {v.duration}s")
    
    图生视频(img2video)
    async with DoubaoChatClient.from_session() as client:
        att = await client.upload_image(open("ref.png", "rb").read(), "ref.png")
        result = await client.generate_video(
            prompt="让画面动起来,镜头缓慢推进",
            ref_image_key=att["uri"],
            ratio="16:9",
        )
    
    视频参数
    参数类型说明
    promptstr视频描述文本(必需)
    ratiostr宽高比:"1:1", "16:9", "9:16"
    camera_movementstr镜头运动方式(可选)
    ref_image_keystr参考图片 key(img2video,可选)
    timeoutfloat最长等待秒数,默认 300
    异步流程
    1. POST /samantha/chat/completion (content_type=2020)
       ↓ SSE 返回文本确认 + fin_reason.async_task.id
    2. POST /samantha/chat/async/stream (body: {task_id, event_id: 0})
       ↓ SSE 长连接等待 1-3 分钟
    3. 收到 content_type=2021 (SamanthaVideoGenerationOutput) → 视频 URL
    

    音乐生成(文生音乐)

    音乐生成是同步的,通常 30-60 秒内返回。返回的音频为 AAC 格式,时长约 60-140 秒。

    最简用法(AI 全自动)
    async with DoubaoChatClient.from_session() as client:
        result = await client.generate_music(prompt="一首轻快的夏日流行歌曲")
        for track in result.tracks:
            print(f"标题: {track.title}")
            print(f"时长: {track.duration}s")
            print(f"音频: {track.audio_url}")
    
    精细控制参数
    result = await client.generate_music(
        prompt="一首关于星空的浪漫民谣",
        genre="Folk",
        mood="Romantic",
        gender="Male",
    )
    
    自定义歌词模式
    result = await client.generate_music(
        prompt="星空之歌",
        lyric="星光洒满夜空 我在这里等你\n银河流淌不息 照亮回家的路",
        genre="Pop",
        gender="Female",
        generation_type="custome_lyric",  # 注意拼写,API 原始值
    )
    
    参数有效值参考

    所有参数值来自 /samantha/skill/pack API(skill_type=9),为首字母大写英文。

    genre(音乐风格)— 11 种:

    API value中文
    Pop流行
    Rock摇滚
    Folk民谣
    Electronic电音
    Hip Hop/Rap嘻哈
    Chinese Style国风
    DJDJ
    R&B/SoulR&B
    Reggae雷鬼
    Punk朋克
    Jazz爵士

    mood(情绪)— 9 种:

    API value中文
    Happy快乐
    Chill放松
    Dynamic/Energetic活力
    Excited兴奋
    Sentimental/Melancholic/Lonely忧郁
    Inspirational/Hopeful鼓舞
    Sorrow/Sad伤感
    Nostalgic/Memory怀旧
    Romantic浪漫

    gender(歌手性别): Male / Female

    generation_type(歌词模式): AI_lyric(AI 写词,默认) / custome_lyric(自定义歌词)

    预设模板

    豆包提供 31 个预设音乐模板(通过 /samantha/skill/pack API 获取,skill_type=9)。

    #标题风格情绪性别
    1醒来RockChillMale
    2关于你FolkSentimental/Melancholic/LonelyFemale
    3玉碎银鞍Chinese StyleSorrow/SadFemale
    4漫漫R&B/SoulChillMale
    5在全宇宙与你相遇RockChillMale
    6牙买加的偶遇ReggaeDynamic/EnergeticMale
    7爱的具象化PopHappyFemale
    8戏中梦Chinese StyleSentimental/Melancholic/LonelyFemale
    9凤梨罐头JazzNostalgic/MemoryMale
    10沉溺的戏JazzSentimental/Melancholic/LonelyMale
    11坠ElectronicChillMale
    12追ElectronicDynamic/EnergeticFemale
    13寻音ElectronicDynamic/EnergeticFemale
    14就粉碎我PunkExcitedMale
    15樱花树下的秘密PopNostalgic/MemoryFemale
    16江南闲梦Chinese StyleChillFemale
    17局外人FolkNostalgic/MemoryFemale
    18归家FolkSentimental/Melancholic/LonelyMale
    19格桑花的等待DJSorrow/SadMale
    20丢了月亮FolkSentimental/Melancholic/LonelyMale
    21夏日微风的低语FolkNostalgic/MemoryFemale
    22迟到PopChillFemale
    23荆棘尽头PopHappyFemale
    24空空PopSentimental/Melancholic/LonelyMale
    25梦里梦外PopSorrow/SadFemale
    26思卿Chinese StyleSorrow/SadMale
    27白瓦Chinese StyleChillMale
    28一镜千年Chinese StyleNostalgic/MemoryMale
    29留学生Hip Hop/RapInspirational/HopefulMale
    30她的故事JazzChillFemale
    31不眠夜PunkExcitedMale

    1. 醒来 — Rock / Chill / Male

    提线木偶般扭动四肢把自己叫醒在清晨
    眼神在五光十色的屏幕前聚焦又涣散
    划过精心包装的视频 掉进虚幻失真的世界
    你在里面嬉笑怒骂 脸孔变换
    曾经大言不惭的梦想还记得吗
    不如冲破这茧房跃入山川湖海的怀抱
    狂奔向苍穹去寻找许巍歌里的蓝莲花
    让自由肆意主宰 你也终将野蛮生长
    

    2. 关于你 — Folk / Sentimental / Female

    你是天边揉碎的白云 轻盈啊
    你是擦肩落下的细雨 醉人啊
    你是高悬天空的明月 遥远啊
    我在夜里寂静 你在眼底蔓延
    我多想 轻握着你的手
    告诉你我所有最深沉的忧愁
    告诉你我的秘密我的温柔
    能否允许我 再陪你走过山高水长
    

    3. 玉碎银鞍 — Chinese Style / Sorrow / Female

    往事如烟 何日重现
    燃尽大殿 天人相隔不复见
    银鞍白马 断弦琵琶
    此生永别玉兰花
    泥沼深陷 万丈深渊
    半生飘摇 恨意涛涛
    刀山火海走一遭 幽冥地狱催人老
    谁将故人悼
    

    4. 漫漫 — R&B/Soul / Chill / Male

    漫漫 怎么让我遇到了你
    好巧你也爱在湖边看下雨
    看行人走走停停
    我们算不算是心有灵犀
    人生一直漫漫慢慢
    漫无目的地将你装在眼底
    慢慢我已离不开你
    慢慢我们一起变老下去
    

    5. 在全宇宙与你相遇 — Rock / Chill / Male

    如戏般的剧本无聊的探索
    宇宙的边缘是未知的轮廓
    人们的生活是否有所掩饰
    灵魂之外还有无尽的渴求
    浩瀚 孤寂 波光粼粼
    和你互相辉映
    捍卫 不朽 这样足够
    还好有你懂我
    

    6. 牙买加的偶遇 — Reggae / Dynamic / Male

    我绕着加勒比海 来到牙买加
    快乐如同棕榈叶 随海风飘动
    偶遇了海边老人 却没有聊天
    他说不要再回头看 你也可以奔跑起来
    Stand up hurry up
    Run up fly up
    我沿着海风飘啊飘啊 就算双脚打结也不累
    我看着浪潮翻啊翻啊 感受这无尽自由时间
    

    7. 爱的具象化 — Pop / Happy / Female

    咖啡香氤氲了晨曦的窗 你在身旁陪我翻阅着时光
    细雨轻敲温柔乡 我们的心跳合奏同频的交响
    午后阳光洒落 捧一束浪漫与你对坐
    街灯下影子交错 爱人啊再把那情话轻讲
    爱的具象化 是漫步宇宙却发现你比星辰明亮
    是化身仓颉 也造不出你名字的分量
    是你看宏大的意象 无法写好爱的具象
    就像我爱你这件事 早已成为我生命的征象
    

    8. 戏中梦 — Chinese Style / Sentimental / Female

    梦是虚实的界限 跨越时间一步千年
    那时笔墨还未染史篇 你仍是少年
    你英年魂归 我迟生千年难吊唁
    骤然清醒 前尘皆散独坐镜前描妆勾面
    金戈铁马吞山河 封狼居胥凯歌旋
    我在台上将戏演 你唯剩史书字里行间
    我唱云遮月 扮将军当年风光无限
    一戏唱罢英雄事 只憾今生前尘无缘相见
    

    9. 凤梨罐头 — Jazz / Nostalgic / Male

    我打开那瓶凤梨罐头 才发现它已过了期
    尝一口过期的希望 酸苦肆意侵袭
    寂静的夜里回忆如潮涌 心却在游离
    从一数到五百的钟响 笑我又唏嘘
    

    10. 沉溺的戏 — Jazz / Sentimental / Male

    我以为我能轻易触碰你
    我真想和你走到时间尽头
    可是啊对你来说 我只是弃之可惜
    这说不清的友情或是爱情 我只能沉溺
    

    11. 坠 — Electronic / Chill / Male

    我把灵魂锁进思念的茧
    放任自己深潜你眸中的海洋
    荒芜的梦中挂满喝醉的星
    摇摇欲坠向你的坐标落下
    

    12. 追 — Electronic / Dynamic / Female

    我透过月亮 看朦胧的未来
    在逐梦的途中歇脚 画幅印象派
    那么忘我啊 连风都听不见
    月光见证我 追在梦的后面
    

    13. 寻音 — Electronic / Dynamic / Female

    在这个潮湿的夜晚风停住不动
    树林也静默 只剩我和你相拥
    就一起到遥远的梦境去找寻
    那回响在灵魂深处的声音
    

    14. 就粉碎我 — Punk / Excited / Male

    每天早上一杯速溶就随便喝
    再像可怜人一样嘶吼怒骂一下
    夜晚在不属于我的城市喝醉游荡
    被生活粉碎被一切粉碎
    就粉碎我的骄傲
    就粉碎我的愤怒
    就粉碎我的执着
    就粉碎我的热情
    

    15. 樱花树下的秘密 — Pop / Nostalgic / Female

    阳光洒落在旧课桌旁 我偷偷看你侧脸的光
    书页间藏着的小心思 和樱花一起悄悄绽放
    小卖部门口故意徘徊 只为和你多一秒遇见
    其实偶尔我也会吃醋 看那女孩与你肩并肩
    听说你喜欢晴天和海 我默默记在心里面
    那些未曾说出口的话 藏在心底成了诗篇
    这粉色秘密微酸又甜 遗憾总让机会擦肩
    但愿未来会有那一天 你能听见我的心弦
    

    16. 江南闲梦 — Chinese Style / Chill / Female

    小桥流水 轻舟摇曳过柳岸
    烟雨蒙蒙 青瓦白墙映江南
    茶香氤氲 书卷轻翻旧时言
    江南闲梦 悠悠岁月慢慢看
    诗意画卷 花开水乡间
    清风拂面 心事皆释然
    岁月静好 笑谈人世间
    在这江南里 梦回旧时年
    

    17. 局外人 — Folk / Nostalgic / Female

    走过林立的高楼 喧闹的街道如此空旷
    逆行汹涌的人潮 犹豫着前进的方向
    我在这城市中漂泊 是拼搏还是挣扎
    舞台上的局外人啊 是坚强还是擅长伪装
    我说理想不重 只压弯了月光
    道路过于宽广 难免迷失方向
    我和这城市不熟 只顾得上闯荡
    白天藏好迷茫 夜晚在梦里飘荡
    

    18. 归家 — Folk / Sentimental / Male

    坐在空空的房间 陪着我的只有吉他
    城市灯火明明灭灭 孤独的人走在长街
    心中的家像远方的月 看得见却触不及边界
    我四处张望 眼眸藏不住失望
    我想有一个家 有小小的沙发和她种的花
    她会抚平我所有伤疤 她会爱我不论冬夏
    心中灯塔忽暗又忽烁 归家梦从未凋落
    异乡霓虹照不亮寂寞 漂泊的心还渴望着落
    

    19. 格桑花的等待 — DJ / Sorrow / Male

    我问你是谁,那心中的爱难猜
    一朵格桑花,她留守在旷野外
    你说爱不在,往事深情成空白
    惊鸿过一瞥,原来寂寞是天籁
    什么样的情欠下何种相思债
    什么样的爱等到下一次花开
    缘尽情难在,还会有什么期待
    相遇即离开,月光洒落秋水外
    

    20. 丢了月亮 — Folk / Sentimental / Male

    他说想要去流浪,像一匹野马
    在草原奔波辗转,听晚风歌唱
    也许他真能找到,这样的地方
    总好过在城市的角落,孤单流放
    这一生啊,埋藏着太多的遗憾
    渴望光啊,却又被现实打得遍体鳞伤
    这青春啊,到底是年少的轻狂
    月亮它啊,终究抵不过六便士的分量
    

    21. 夏日微风的低语 — Folk / Nostalgic / Female

    想你像树荫下的微风
    轻轻吹过我心头的夏天
    盼你如晨曦穿过小窗
    一丝丝光芒映在旧墙
    你是我日复一日的期待
    是每条小路上的远方
    在每个普通的时刻里
    你是无尽思念的风光
    

    22. 迟到 — Pop / Chill / Female

    床头放着闹钟 怀里抱着猫
    喂食器一工作 猫就喵喵叫
    可是为什么 我还是睡过头
    难道神明在说 我注定迟到
    相遇迟到相恋迟到 分手也迟到
    追赶不上挽留不了 只剩下苦笑
    我与你的happyend 总是差一点
    如果抵达不了 干脆逃开你的怀抱
    

    23. 荆棘尽头 — Pop / Happy / Female

    多少次满身污泥,多少次人海沉浮
    你从我背后走来,带动温热的晚风
    水雾稀薄了,空气旋转了
    绝望消散了,荡气回肠了
    破除了荆棘,将苦化作了甜蜜
    站在我身后,为累赋格了意义
    星垂低语耳边呢喃
    说千万别再走丢了
    

    24. 空空 — Pop / Sentimental / Male

    关了灯在屋中 心太空
    失去所有联络 没行踪
    模糊的空气里 要发疯
    乌云密布的我 是黑洞
    比一块冰更寂更冷
    比一尾鱼更哑更聋
    沉溺在自我世界 无视情感涌动
    深陷于太空四季 梦境与诗中
    

    25. 梦里梦外 — Pop / Sorrow / Female

    在梦里爱上你
    所有斑驳都重生奕奕
    在梦外离开你
    爱的忍耐都化为灰燃
    梦中阳光耀眼
    醒来只见黑暗幽远
    走不出望不穿
    爱的语言都成为云烟
    

    26. 思卿 — Chinese Style / Sorrow / Male

    提笔绘,浮生卷卷落画,雕琢我心扉
    叹只叹,此景难入你眼,空留了伤悲
    骤雨催,车马滚滚印辙,装下离人泪
    却思归,自此山高水远,恐是再难回
    且看那风月笑,知是情深不可往
    饮浊酒一杯,在红尘染尽爱恨憔悴
    又闻那落花飞,点了流水尚余味
    此一生,只一生,凭回忆将卿魂牵梦追
    

    27. 白瓦 — Chinese Style / Chill / Male

    轻踏白瓦巷 雨后晴空长
    柳絮沾露珠 釉色染霜凉
    古道旁桃花香 纸伞下人相望
    岁月轻抚过 留下一抹妆
    白瓦映月光 故事在回响
    烟雨水墨里 勾勒过往
    青石板街旁 谁家炊烟扬
    一幕幕画卷 藏匿旧时芳华香
    

    28. 一镜千年 — Chinese Style / Nostalgic / Male

    铜镜轻拂尘 岁月留痕深
    镜中映出旧时颜 笑语盈盈似花绽
    镜中影似水流年 恍若隔世梦一场
    镜外人诉尽沧桑 昔日风华已成殇
    精雕细琢星云纹 凤鸟欲飞蟠龙腾
    镜里千秋照出历史悠悠
    汉唐宋明时光转 故事长长已泛黄
    你看那谁的手拂过往事幽幽
    

    29. 留学生 — Hip Hop/Rap / Inspirational / Male

    打包20刀的一荤一素
    回到尽头那间standard room
    进门先和室友打个招呼
    不是Sam是袋鼠和蜘蛛
    没有尖叫也不会被吓哭
    我早就对此熟视无睹
    比起危险还是essay更痛苦
    我埋头在房间极限赶due
    都说留学必然经历四个阶段
    兴奋焦虑疯癫和麻木感
    陌生的地域,毕业的压力
    连吃饱饭都那么艰难
    在异国看同一轮太阳落下
    其实我也很想家
    还好心态和胃很抗压
    留学生的信念不会轻易崩塌
    

    30. 她的故事 — Jazz / Chill / Female

    玫瑰会奔向远方 伴着荒郊月亮
    夜莺为她歌唱 南风也为她奔忙
    她会始终绽放 她会给你芳香
    她会一路歌唱 去她自己的乡
    

    31. 不眠夜 — Punk / Excited / Male

    不想听的电话就按掉
    不想见的人就让他走开
    不想装傻就尽情发泄吧
    失败的梦想就让它算了吧
    我要我要我要一个不眠夜
    鼓点敲击我的大脑 吞没我的疯狂
    那个瞬间 我好像看到了天堂。
    哪怕只能暂时逃避 我也只想逃避
    
    返回结果字段

    MusicGenerationResult.tracks 列表中每个 GeneratedMusic 包含:

    字段类型说明
    audio_urlstr音频下载 URL(AAC/.mp4,抖音 CDN)
    titlestrAI 生成的歌曲标题
    durationfloat时长(秒),通常 60-140s
    lyricsstr完整歌词文本
    cover_urlstr封面图 URL
    vidstr抖音视频 ID(内部标识)

    统一 API 服务(OpenAI 兼容)

    一个服务暴露所有能力,兼容 OpenAI SDK 格式。设计为在 Linux 无头服务器上长期运行。

    部署

    安装依赖
    pip install aiohttp fastapi pydantic uvicorn httpx playwright playwright-stealth python-multipart
    playwright install chromium
    
    本地开发启动
    python -m doubao2api
    # 默认监听 0.0.0.0:9090,无认证
    
    生产部署(Ubuntu)
    DOUBAO_API_KEY=your-secret-key \
    DOUBAO_HOST=0.0.0.0 \
    DOUBAO_PORT=9090 \
    DOUBAO_RPM_LIMIT=30 \
    DOUBAO_BROWSER_DATA=/opt/doubao2api/.browser_data \
    python -m doubao2api
    
    systemd 服务(推荐)
    # /etc/systemd/system/doubao-api.service
    [Unit]
    Description=Doubao Chat API
    After=network.target
    
    [Service]
    Type=simple
    User=doubao
    WorkingDirectory=/opt/doubao
    Environment=DOUBAO_API_KEY=your-secret-key
    Environment=DOUBAO_HOST=0.0.0.0
    Environment=DOUBAO_PORT=9090
    Environment=DOUBAO_BROWSER_DATA=/opt/doubao2api/.browser_data
    ExecStart=/usr/bin/python3 -m doubao2api
    Restart=always
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
    
    sudo systemctl daemon-reload
    sudo systemctl enable --now doubao-api
    
    Nginx 反向代理(可选)
    server {
        listen 443 ssl;
        server_name doubao-api.example.com;
    
        location / {
            proxy_pass http://127.0.0.1:9090;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_buffering off;           # SSE 流式必须关闭缓冲
            proxy_read_timeout 300s;       # 视频生成需要长超时
        }
    }
    

    环境变量

    变量默认值说明
    DOUBAO_PORT9090监听端口
    DOUBAO_HOST0.0.0.0监听地址
    DOUBAO_API_KEY(空=无认证)Bearer token。设为 any 接受任意非空 key
    DOUBAO_RPM_LIMIT20每分钟请求限制(所有端点共享)
    DOUBAO_HEADLESStrueChromium 是否无头运行
    DOUBAO_BROWSER_DATA~/.doubao_browserChromium 持久化用户目录
    DOUBAO_NOVNC_URL自动推断Admin 面板中的 noVNC 地址
    DOUBAO_NOVNC_PASSWORD空自动拼接到 noVNC URL 的密码参数

    认证

    设置 DOUBAO_API_KEY 后,API 和 Admin 端点需要 Bearer token;不设置时不启用认证:

    Authorization: Bearer your-api-key
    
    • DOUBAO_API_KEY 未设置时:无认证,所有请求直接通过
    • DOUBAO_API_KEY=any:接受任意非空 Bearer token
    • DOUBAO_API_KEY=sk-xxx:仅接受完全匹配的 token

    会话管理

    启动行为:服务启动时打开持久化 Chromium 用户目录(DOUBAO_BROWSER_DATA),如果浏览器目录内已有登录态会自动复用。

    浏览器 watchdog:后台每 30 秒检查浏览器是否响应,如果 Chromium 进程异常会自动重启。

    风控处理:如果接口返回 710022004,服务会在 /health 中标记 needs_captcha=true,此时需要通过 noVNC 或重新登录处理风控,再调用 /auth/reset_captcha 恢复服务。

    首次部署 Session 获取:

    # 方式 1:通过 Dashboard 扫码(推荐)
    # 访问 http://host:port/admin?key=YOUR_API_KEY → 登录 Tab → 扫码
    # 登录成功后 3 秒自动跳转概览页
    
    # 方式 2:API 扫码登录
    curl -X POST http://localhost:9090/v1/session/qr-login \
      -H "Authorization: Bearer YOUR_KEY"
    # → 返回 base64 QR 码图片,用豆包 App 扫码
    # 轮询状态:
    curl http://localhost:9090/v1/session/qr-login \
      -H "Authorization: Bearer YOUR_KEY"
    
    # 如遇验证码/风控,可打开 Admin 登录页里的 noVNC 手动处理
    

    Admin Dashboard

    内置 Web 管理面板(Vue 3 单文件应用,零构建依赖)。

    访问:http://host:port/admin?key=YOUR_API_KEY

    页面功能
    概览Session 状态、系统配置、Cookie 详情表格、测活按钮
    登录QR 扫码登录、noVNC 手动登录、浏览器截图
    API 测试选择模型发送请求,支持流式/非流式,思维链折叠展示
    请求日志最近 100 条请求记录(5s 自动刷新)
    • 如果设置了 DOUBAO_API_KEY,HTML 页面和数据 API 都需要认证
    • 概览页每 10 秒自动刷新 session 状态
    • "测活"按钮主动发消息验证 session 有效性

    模型列表

    模型 ID类型need_deep_think说明
    doubaochat0快速模式(默认)
    doubao-thinkchat1思考模式(带思维链)
    doubao-expertchat3专家模式(深度推理)
    doubao-prochat0快速模式别名
    doubao-imageimage—图片生成
    doubao-videovideo—视频生成
    doubao-musicaudio—音乐生成

    端点详细规范

    GET /health

    健康检查,无需认证。

    响应:

    {
      "status": "ok",
      "logged_in": true,
      "consecutive_failures": 0,
      "needs_captcha": false,
      "last_error_code": 0
    }
    
    GET /v1/models

    返回所有可用模型列表。

    响应:

    {
      "object": "list",
      "data": [
        {"id": "doubao", "object": "model", "owned_by": "doubao", "created": 0},
        {"id": "doubao-think", "object": "model", "owned_by": "doubao", "created": 0}
      ]
    }
    
    POST /v1/chat/completions

    OpenAI 兼容的聊天补全端点。

    请求体:

    {
      "model": "doubao-think",
      "messages": [
        {"role": "system", "content": "你是一个助手"},
        {"role": "user", "content": "你好"}
      ],
      "stream": true
    }
    

    文件输入:当前统一服务支持 OpenAI 风格的 file_url,仅支持非流式请求。图片输入的 image_url 结构暂未在统一服务中解析。

    参数类型必填说明
    modelstring否模型 ID,默认 doubao
    messagesarray是消息数组,支持 system/user/assistant 角色
    streambool否是否流式返回,默认 false
    conversation_idstring否多轮对话 ID。首次不传,响应中返回新 ID,后续请求带上即可续接上下文
    bot_idstring否切换 Bot,默认 7338286299411103781
    temperaturefloat否温度参数(保留字段,当前不影响行为)
    max_tokensint否最大 token 数(保留字段)

    非流式响应:

    {
      "id": "chatcmpl-abc123",
      "object": "chat.completion",
      "created": 1700000000,
      "model": "doubao-think",
      "conversation_id": "38427336493867522",
      "choices": [{
        "index": 0,
        "message": {
          "role": "assistant",
          "content": "回答内容",
          "reasoning_content": "思维链内容(仅思考/专家模式)",
          "conversation_id": "38427336493867522"
        },
        "finish_reason": "stop"
      }],
      "usage": {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0}
    }
    

    多轮对话示例:

    # 第一轮:不传 conversation_id,响应中返回新 ID
    RESP=$(curl -s http://localhost:9090/v1/chat/completions \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"model":"doubao","messages":[{"role":"user","content":"我叫小明"}]}')
    CONV_ID=$(echo $RESP | jq -r '.conversation_id')
    
    # 第二轮:带上 conversation_id,模型记住上下文
    curl http://localhost:9090/v1/chat/completions \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d "{\"model\":\"doubao\",\"messages\":[{\"role\":\"user\",\"content\":\"我叫什么名字?\"}],\"conversation_id\":\"$CONV_ID\"}"
    # → "你叫小明"
    

    流式响应(SSE):

    data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1700000000,"model":"doubao-think","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
    
    data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1700000000,"model":"doubao-think","choices":[{"index":0,"delta":{"reasoning_content":"思考中..."},"finish_reason":null}]}
    
    data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1700000000,"model":"doubao-think","choices":[{"index":0,"delta":{"content":"回答"},"finish_reason":null}]}
    
    data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1700000000,"model":"doubao-think","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
    
    data: [DONE]
    

    错误码:

    HTTP 状态说明
    400无效模型或空消息
    401认证失败
    503未登录、浏览器未初始化或需要验证码
    502上游错误(豆包 API 异常)

    POST /v1/files

    文件上传端点。上传文件后可在 /v1/chat/completions 中通过 file_url 内容类型引用。

    请求格式:multipart/form-data

    字段类型必填说明
    filefile是要上传的文件

    curl 示例:

    # 上传 PDF 文件
    curl http://localhost:9090/v1/files \
      -F "[email protected]"
    
    # 上传代码文件
    curl http://localhost:9090/v1/files \
      -F "[email protected]"
    
    # 上传 CSV 数据
    curl http://localhost:9090/v1/files \
      -F "[email protected]"
    

    响应:

    {
      "id": "tos-cn-i-ik7evvg4ik/3d1fe926a54849ebaa8f69943889393a.pdf",
      "object": "file",
      "filename": "document.pdf",
      "bytes": 102400,
      "uri": "tos-cn-i-ik7evvg4ik/3d1fe926a54849ebaa8f69943889393a.pdf",
      "file_type": "pdf",
      "purpose": "assistants"
    }
    
    响应字段类型说明
    idstring与 uri 相同,兼容 OpenAI 文件对象格式
    objectstring固定 "file"
    filenamestring原始文件名
    bytesint文件大小(字节)
    uristringTOS 存储路径(可用于后续引用)
    file_typestring文件扩展名
    purposestring固定 "assistants"

    错误码:

    HTTP 状态说明
    400缺少 file 字段或非 multipart 请求
    401认证失败
    429速率限制
    502上传失败(TOS 存储异常)

    GET /v1/files/download

    获取已上传文件的临时 CDN 下载链接。配合 /v1/files 使用,实现完整的上传→下载流程。

    Query 参数:

    参数类型必填说明
    uristring是/v1/files 返回的 TOS URI
    expireint否期望有效期秒数(实际固定 7 天,此参数无效)

    curl 示例:

    curl "http://localhost:9090/v1/files/download?uri=tos-cn-i-ik7evvg4ik/xxx.txt"
    

    响应:

    {
      "url": "https://p3-flow-sign.byteimg.com/tos-cn-i-ik7evvg4ik/xxx.txt?x-expires=...",
      "uri": "tos-cn-i-ik7evvg4ik/xxx.txt",
      "expires_in": 3600
    }
    
    响应字段类型说明
    urlstringCDN 下载链接(有效期 7 天)
    uristring原始 TOS URI
    expires_inint请求的过期时间(实际由服务端决定)

    完整上传→下载流程:

    # 1. 上传文件
    RESPONSE=$(curl -s http://localhost:9090/v1/files -F "[email protected]")
    URI=$(echo $RESPONSE | jq -r '.uri')
    echo "上传成功: $URI"
    
    # 2. 获取下载链接(可反复调用,每次返回新的 7 天有效 URL)
    DOWNLOAD_URL=$(curl -s "http://localhost:9090/v1/files/download?uri=$URI" | jq -r '.url')
    
    # 3. 下载文件
    curl -o downloaded.pdf "$DOWNLOAD_URL"
    

    存储特性:

    项目限制
    单文件大小上限1 GB
    上传速度~7 MB/s(取决于网络)
    下载 URL 有效期固定 7 天(expire 参数无效)
    URI 持久性可无限次重新获取下载 URL
    底层存储ByteDance veImageX 标准存储(默认永久保留)
    支持格式60+ 种(PDF/DOCX/代码/图片等,见支持列表)

    存储持久性说明:根据 veImageX 官方文档,标准存储类型的文件默认永久保留,不会自动删除(除非服务方配置了生命周期策略)。实测中 URI 可无限次刷新获取新的 7 天下载链接,未观察到文件被删除的情况。但由于我们使用的是豆包内部的 veImageX 服务,无法排除字节跳动未来调整内部策略的可能性,建议重要文件自行备份。


    POST /v1/images/upload

    图片上传端点。上传图片后返回 CDN URL,可直接用于 /v1/chat/completions 的 image_url 内容类型,无需 base64 编码。

    适用场景:本地大图片、避免 base64 膨胀(+33% 体积)。

    请求格式:multipart/form-data

    字段类型必填说明
    filefile是图片文件(png/jpg/webp)

    curl 示例:

    # 上传图片
    curl http://localhost:9090/v1/images/upload \
      -F "[email protected]"
    

    响应:

    {
      "url": "https://p-vcloud.byteimg.com/tos-cn-i-ik7evvg4ik/xxx.png~tplv-...",
      "key": "tos-cn-i-ik7evvg4ik/xxx.png",
      "filename": "photo.jpg",
      "bytes": 2048576
    }
    
    响应字段类型说明
    urlstringCDN URL,直接用于 image_url.url
    keystringTOS 存储路径
    filenamestring原始文件名
    bytesint文件大小(字节)

    完整使用流程:

    # 1. 上传图片
    URL=$(curl -s http://localhost:9090/v1/images/upload \
      -F "[email protected]" | jq -r '.url')
    
    # 2. 在聊天中引用(无需 base64)
    curl http://localhost:9090/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d "{
        \"model\": \"doubao-expert\",
        \"messages\": [{\"role\": \"user\", \"content\": [
          {\"type\": \"text\", \"text\": \"描述这张图片\"},
          {\"type\": \"image_url\", \"image_url\": {\"url\": \"$URL\"}}
        ]}],
        \"stream\": true
      }"
    

    已上传的图片 URL(含 tos-cn-i-)会被自动识别,不会重复上传。


    在 /v1/chat/completions 中使用文件

    有两种方式在聊天中附带文件:

    方式 1:使用 file_url 内容类型(自动上传)

    服务器会自动下载并上传文件到豆包存储:

    # 通过 base64 data URI 传递文件内容
    curl http://localhost:9090/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "doubao",
        "messages": [{
          "role": "user",
          "content": [
            {"type": "file_url", "file_url": {"url": "data:text/plain;base64,SGVsbG8gV29ybGQ="}},
            {"type": "text", "text": "这个文件里写了什么?"}
          ]
        }]
      }'
    
    # 通过 HTTP URL 传递文件(服务器会下载)
    curl http://localhost:9090/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "doubao",
        "messages": [{
          "role": "user",
          "content": [
            {"type": "file_url", "file_url": {"url": "https://example.com/report.pdf"}},
            {"type": "text", "text": "总结这份报告的要点"}
          ]
        }]
      }'
    

    方式 2:先上传再引用(适合大文件或重复引用)

    先通过 /v1/files 上传,然后在多次对话中复用同一个文件 URI:

    # Step 1: 上传文件(只需一次)
    curl -s http://localhost:9090/v1/files -F "[email protected]"
    # -> {"uri": "tos-cn-i-ik7evvg4ik/xxx.pdf", "filename": "report.pdf", "bytes": 102400, ...}
    
    # Step 2: 在对话中直接引用 TOS URI(可多次复用,不会重复上传)
    curl http://localhost:9090/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "doubao-expert",
        "messages": [{"role": "user", "content": [
          {"type": "file_url", "file_url": {
            "url": "tos-cn-i-ik7evvg4ik/xxx.pdf",
            "name": "report.pdf",
            "size": 102400
          }},
          {"type": "text", "text": "总结这份报告的要点"}
        ]}]
      }'
    

    file_url 内容类型参数:

    {
      "type": "file_url",
      "file_url": {
        "url": "data:application/pdf;base64,...",
        "name": "report.pdf",
        "size": 102400
      }
    }
    
    字段类型必填说明
    urlstring是文件来源,支持三种格式:• tos-cn-i-xxx/yyy.pdf — 已上传的 TOS URI(不会重复上传)• data:{mime};base64,{data} — 直接传递文件内容• https://example.com/file.pdf — HTTP(S) URL,服务器会下载
    namestring否文件名(使用 TOS URI 时建议提供)
    sizeint否文件大小字节数(使用 TOS URI 时建议提供)

    支持混合多种内容类型:

    {
      "model": "doubao",
      "messages": [{
        "role": "user",
        "content": [
          {"type": "file_url", "file_url": {"url": "data:text/csv;base64,..."}},
          {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}},
          {"type": "text", "text": "对比图表和数据是否一致"}
        ]
      }]
    }
    

    注意:

    • 文件上传受速率限制(与聊天共享 RPM 配额)
    • 上传的文件存储在 ByteDance TOS,URI 有效期较长但非永久
    • 单次对话可附带多个文件,但总量建议不超过 5 个
    • 超大文件(>10MB)上传可能较慢,建议设置较长的请求超时

    POST /v1/images/generations

    图片生成端点。

    请求体:

    {
      "prompt": "一只猫在月球上",
      "model": "doubao-image",
      "ratio": "16:9",
      "size": "1792x1024"
    }
    
    参数类型必填说明
    promptstring是图片描述
    modelstring否固定 doubao-image
    ratiostring否豆包比例:1:1/16:9/9:16/4:3/3:4;优先级高于 size
    sizestring否OpenAI 风格尺寸:1024x1024/1792x1024/1024x1792/1024x768/768x1024;也可直接传比例字符串
    ref_image_keystring否参考图片 key(图生图)。通过 /v1/images/upload 上传后获取 uri 字段

    图生图示例(先上传参考图,再生成):

    # 1. 上传参考图片,获取 uri
    URI=$(curl -s http://localhost:9090/v1/images/upload \
      -F "[email protected]" | jq -r '.uri')
    
    # 2. 以参考图为基础生成新图
    curl http://localhost:9090/v1/images/generations \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d "{\"prompt\":\"将这张图片转为水彩画风格\",\"ref_image_key\":\"$URI\",\"ratio\":\"16:9\"}"
    

    响应:

    {
      "created": 1700000000,
      "data": [
        {
          "url": "https://p-vcloud.byteimg.com/...",
          "revised_prompt": "一只猫在月球上"
        }
      ]
    }
    

    POST /v1/video/generations

    视频生成端点。当前接口会在请求内等待任务结果,成功后直接返回视频列表。

    请求体:

    {
      "model": "doubao-video",
      "prompt": "一只柴犬在雪地奔跑",
      "ratio": "16:9"
    }
    
    参数类型必填说明
    promptstring是视频描述
    modelstring否固定 doubao-video
    ratiostring否1:1/16:9/9:16,也可传 OpenAI 风格 size 后自动映射

    响应:

    {
      "created": 1700000000,
      "data": [
        {"video_url": "https://...", "cover_url": "https://...", "duration": 5.0, "width": 1920, "height": 1080}
      ]
    }
    

    POST /v1/audio/generations

    音乐生成端点。

    请求体:

    {
      "model": "doubao-music",
      "prompt": "一首关于夏天的轻快流行歌",
      "genre": "Pop",
      "lyric": "可选歌词"
    }
    
    参数类型必填说明
    promptstring是歌曲描述
    modelstring否固定 doubao-music
    lyricstring否自定义歌词
    genrestring否流派

    响应:

    {
      "created": 1700000000,
      "data": [
        {
          "audio_url": "https://v3-web.douyinvod.com/...",
          "title": "夏日微风",
          "duration": 95.5,
          "lyrics": "完整歌词...",
          "cover_url": "https://..."
        }
      ]
    }
    

    GET /auth/status

    查看当前 session 健康状态。

    响应:

    {
      "logged_in": true,
      "is_ready_flag": true,
      "login_button_visible": false,
      "page_url": "https://www.doubao.com/chat/",
      "device_id": "...",
      "web_id": "..."
    }
    

    /admin/api/status 返回同样结构。


    POST /v1/session/qr-login

    启动 QR 扫码登录流程。

    响应:

    {
      "status": "qr_ready",
      "qr_image_base64": "iVBORw0KGgo...",
      "message": "Scan QR code with Doubao mobile app."
    }
    
    GET /v1/session/qr-login

    轮询扫码状态。

    响应:

    // 等待扫码
    {"status": "pending"}
    
    // 登录成功
    {"status": "success", "message": "Login successful, session updated", "cookies_count": 8}
    
    // 失败
    {"status": "failed", "error": "二维码已过期"}
    

    GET /admin

    管理面板 HTML 页面(无需认证)。

    GET /admin/api/logs

    最近 100 条请求日志。

    GET /admin/api/system

    系统信息(Python 版本、运行时间、配置等)。

    GET /admin/api/cookies

    当前 session 的 Cookie 详情。

    使用 OpenAI Python SDK

    from openai import OpenAI
    
    client = OpenAI(base_url="http://127.0.0.1:9090/v1", api_key="your-key")
    
    # 流式聊天
    stream = client.chat.completions.create(
        model="doubao-think",
        messages=[{"role": "user", "content": "解释量子纠缠"}],
        stream=True,
    )
    for chunk in stream:
        delta = chunk.choices[0].delta
        if delta.content:
            print(delta.content, end="")
    
    # 非流式聊天
    response = client.chat.completions.create(
        model="doubao-expert",
        messages=[{"role": "user", "content": "证明勾股定理"}],
    )
    print(response.choices[0].message.content)
    
    # 图片生成
    images = client.images.generate(
        model="doubao-image",
        prompt="一只宇航员猫咪",
        extra_body={"ratio": "1:1"},
    )
    print(images.data[0].url)
    
    # 带文件的聊天(通过 base64 data URI)
    import base64
    file_data = open("report.pdf", "rb").read()
    b64 = base64.b64encode(file_data).decode()
    
    response = client.chat.completions.create(
        model="doubao",
        messages=[{
            "role": "user",
            "content": [
                {"type": "file_url", "file_url": {"url": f"data:application/pdf;base64,{b64}"}},
                {"type": "text", "text": "总结这份文档的核心观点"},
            ],
        }],
    )
    print(response.choices[0].message.content)
    

    使用 curl

    # 流式聊天
    curl -N http://localhost:9090/v1/chat/completions \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"model":"doubao-think","messages":[{"role":"user","content":"你好"}],"stream":true}'
    
    # 上传文件
    curl http://localhost:9090/v1/files \
      -H "Authorization: Bearer sk-xxx" \
      -F "[email protected]"
    
    # 带文件的聊天(base64 方式)
    FILE_B64=$(base64 -w0 document.pdf)
    curl http://localhost:9090/v1/chat/completions \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d "{\"model\":\"doubao\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"file_url\",\"file_url\":{\"url\":\"data:application/pdf;base64,$FILE_B64\"}},{\"type\":\"text\",\"text\":\"总结文档\"}]}]}"
    
    # 带文件的聊天(URL 方式,服务器自动下载)
    curl http://localhost:9090/v1/chat/completions \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"model":"doubao","messages":[{"role":"user","content":[{"type":"file_url","file_url":{"url":"https://example.com/report.pdf"}},{"type":"text","text":"总结这份报告"}]}]}'
    
    # 图片生成
    curl http://localhost:9090/v1/images/generations \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"prompt":"一只猫在月球上","ratio":"16:9"}'
    
    # 视频生成(请求内等待结果)
    curl http://localhost:9090/v1/video/generations \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"prompt":"一只柴犬在雪地奔跑","ratio":"16:9"}'
    
    # 音乐生成
    curl http://localhost:9090/v1/audio/generations \
      -H "Authorization: Bearer sk-xxx" \
      -H "Content-Type: application/json" \
      -d '{"prompt":"一首轻快的夏日歌曲","genre":"Pop"}'
    

    Bot ID

    Bot ID说明多模态备注
    7338286299411103781当前统一服务默认 Bot文件问答/多媒体生成BrowserClient.DEFAULT_BOT_ID

    说明:client.py 中仍保留旧版 DoubaoChatClient 的 Bot ID 常量;当前统一服务主路径使用 BrowserClient,默认 Bot ID 为 7338286299411103781。

    底层模型与路由

    模型家族

    豆包底层使用字节跳动自研的 Seed 大模型。三模式(快速/思考/专家)共用同一个 Seed 模型,区别在于思考/专家模式注入了 Chain-of-Thought 提示。

    seed_intention 路由表

    豆包采用内容驱动的智能路由,收到消息后先分析意图再分发到对应 Agent:

    intentiondetailagent触发条件
    seed_maindefaultAgent-Chat闲聊、推理、翻译
    seed_mainknowledgeAgent-Knowledge知识问答
    seed_mainwritingAgent-InnerCreation创作
    browsingcomplex_browsingAgent-Knowledge实时搜索
    multi_agentAgent-CodeAgent-Code代码执行

    模式切换参数

    need_deep_think模式completion_option思考链
    0快速use_deep_think: false无
    1思考use_deep_think: true有(10040+10000)
    3专家use_deep_think: true, use_auto_cot: true有(10040+10000)

    API 响应中的模型元数据

    SSE 事件的 message.ext 字段包含:

    字段含义示例值
    llm_model_type模型内部 ID38, 1733208237
    llm_intention调度意图seed_main / browsing
    llm_intention_detail细分意图default / Agent-Code
    input_tokens输入 token 数动态
    output_tokens输出 token 数动态

    火山引擎 ARK API 模型名称参考

    系列model_id说明
    豆包 2.0 Prodoubao-seed-2-0-pro专家模式对应
    豆包 2.0 Litedoubao-seed-2-0-lite快速模式对应
    豆包 2.0 Minidoubao-seed-2-0-mini低延迟高并发
    豆包 2.0 Codedoubao-seed-2-0-code-preview-260215编程场景
    豆包 1.5 Pro 32Kdoubao-1-5-pro-32k-250115上一代主力
    豆包 1.6 思考doubao-seed-1-6-thinking-250715深度推理
    豆包 1.6 快速思考doubao-seed-1-6-flash-250615快速推理

    技术细节

    认证流程

    通过 QR 扫码登录获取完整 session,并注入到 Playwright 持久化浏览器上下文:

    1. 请求 CSRF token(GET https://www.doubao.com)
    2. 获取 QR 码(POST /passport/web/scan_qrcode/)
    3. 用户用豆包 App 扫码确认
    4. 获取 sessionid、ttwid、passport_csrf_token 等 Cookie
    5. 注入 Chromium 用户目录,后续启动复用 DOUBAO_BROWSER_DATA

    请求格式

    /chat/completion(聊天主端点)

    当前统一服务的文本聊天、文件问答使用 /chat/completion。请求通过 Playwright 页面内的 fetch() 发出,ByteDance 前端 JS hook 自动拦截并注入 a_bogus + msToken 签名,确保请求指纹与浏览器完全一致。

    关键点:

    项目值
    URL/chat/completion?aid=497858&device_platform=web&...(hook 自动追加 a_bogus)
    MethodPOST
    Content-Typeapplication/json
    签名浏览器 fetch hook 自动注入(无需手动调用)
    CSRF从 passport_csrf_token Cookie 自动提取并设为 header
    msTokenfetch hook 自动从 Cookie 读取并注入
    传输方式page.evaluate() + expose_function 回调桥接 SSE 流
    /samantha/chat/completion(图片/视频/音乐生成端点)

    图片、视频、音乐生成使用 /samantha/chat/completion。请求体为 JSON 明文对象:

    {
      "messages": [
        {
          "content": "{\"text\":\"你的问题\"}",
          "content_type": 2001,
          "attachments": [],
          "references": []
        }
      ],
      "completion_option": {
        "is_regen": false,
        "with_suggest": true,
        "need_create_conversation": true,
        "launch_stage": 1,
        "is_replace": false,
        "is_delete": false,
        "is_ai_playground": false,
        "memory_type": 2,
        "message_from": 0,
        "use_deep_think": true,
        "use_auto_cot": false,
        "resend_for_regen": false,
        "enable_commerce_credit": false
      },
      "evaluate_option": {"web_ab_params": ""},
      "local_conversation_id": "<timestamp>_<uuid>",
      "local_message_id": "<timestamp>_<uuid>"
    }
    

    关键字段:

    字段类型说明
    messages[].contentstringJSON.stringify({text: "..."})
    messages[].content_typeint2001 = SamanthaText
    completion_option.use_deep_thinkbool启用深度思考
    completion_option.use_auto_cotbool自动 CoT
    completion_option.launch_stageint1 = Release
    completion_option.memory_typeint2 = ToolMemory

    SSE 事件类型

    event_type枚举名说明
    1HEARTBEAT心跳
    2001CMPL文本补全块
    2002ACK消息确认(含 conversation_id)
    2003FIN流结束
    2004CMD命令
    2005ERR错误
    2010VERBOSE详细元数据(seed_intention 等)

    content_type 枚举

    值枚举名说明
    2001SamanthaText普通文本
    2002SamanthaSuggest推荐问题
    2003SamanthaLoading加载状态("深度思考中")
    2005SamanthaMusicGenInput音乐生成输入
    2008SamanthaSearchText思考链增量文本
    2009SamanthaImageInput图片输入
    2010SamanthaImageOutput图片输出
    2020SamanthaVideoGenerationInput视频生成输入
    2021SamanthaVideoGenerationOutput视频生成输出
    10000SamanthaTextV2主回答文本(思考/专家模式)
    10040BlockTypeThink思考内容块

    思考链提取

    聊天流中通过 block_type=10040 切换思考状态,block_type=10000 或 CHUNK_DELTA 承载文本:

    SSE event_type=2001 (CMPL)
      ├─ content_type=10040 → 思考状态块(BLOCK_THINKING)
      ├─ content_type=10000 → 主回答文本
      ├─ content_type=2008  → 思考链增量文本 (content.think)
      ├─ content_type=2001  → 最终回答文本
      └─ content_type=2002  → 推荐问题
    SSE event_type=2010 (VERBOSE) → 模型调度意图
    SSE event_type=2002 (ACK) → conversation_id
    SSE event_type=2003 (FIN) → 流结束
    

    Session 过期与风控检测

    端点过期信号
    /chat/completionSSE error_code / STREAM_ERROR
    /samantha/chat/completionJSON 错误或 SSE event_type=2005
    风控验证码710022004

    触发 710022004 后,服务会标记 needs_captcha=true,/health 会暴露该状态,_get_client() 会拒绝继续请求,直到人工完成验证并调用 /auth/reset_captcha。

    msToken 与风控

    msToken 是字节跳动前端 JSSDK(BDMS/Slardar)生成的设备指纹 token,存储在 .bytedance.com 域下。格式为 136 字节随机数据的 base64url 编码(184 字符)。

    本项目策略:所有 API 请求通过浏览器内 fetch() 发出,ByteDance 的 fetch hook 自动从 Cookie 读取 msToken 并注入请求参数,无需手动管理。文件上传端点(upload_file/upload_image)仍使用 httpx + frontierSign 签名,启动时从 Cookie 读取 msToken。

    搜索工具调用捕获

    当豆包模型判断需要联网搜索时,SSE 流中会出现 block_type=10025(search_query_result_block)事件。本项目完整捕获这些事件并通过 API 暴露。

    SSE 流中的搜索事件结构:

    {
      "block_type": 10025,
      "content": {
        "search_query_result_block": {
          "summary": "搜索 3 个关键词,参考 23 篇资料",
          "queries": ["关键词1", "关键词2", "关键词3"],
          "results": [
            {"text_card": {"title": "...", "url": "...", "summary": "...", "source_name": "..."}}
          ]
        }
      },
      "is_finish": true
    }
    

    API 响应中的搜索结果:

    流式响应通过 delta.search_results 传递:

    {
      "choices": [{
        "delta": {
          "search_results": {
            "summary": "搜索 3 个关键词,参考 23 篇资料",
            "queries": ["关键词1", "关键词2"],
            "results": [
              {"title": "...", "url": "...", "summary": "...", "source": "..."}
            ]
          }
        }
      }]
    }
    

    Admin 面板会合并多次增量搜索结果,并显示关键词、来源和摘要。

    已知 block_type 列表:

    block_type含义处理方式
    10000文本块(思维链/回答)拼接为 text/thinking
    10024通用工具块(generic_tool_block)提取 title → tool_info
    10025搜索结果块(search_query_result_block)完整解析 → search_info
    10040思维链分隔符状态机切换 thinking/answer
    10052附件块(图片上传)仅用于请求构建
    10101加载状态块(loading_block)提取 text → tool_info

    项目结构

    doubao2api/
    ├── __init__.py          # 公开 API
    ├── __main__.py          # CLI 入口
    ├── browser_client.py    # BrowserClient(浏览器内 fetch + expose_function 流式桥接)
    ├── client.py            # DoubaoChatClient(旧版独立客户端,保留兼容)
    ├── unified_server.py    # 统一 API 服务(FastAPI,OpenAI 兼容)
    ├── session.py           # Cookie 加载(JSON 文件)
    ├── sse.py               # Server-Sent Events 解析器
    ├── qr_login.py          # QR 扫码登录(纯 HTTP)
    ├── captcha_handler.py   # 验证码处理
    ├── captcha_server.py    # 验证码本地 Web 服务
    └── static/
        └── admin.html       # Admin Dashboard(Vue 3)
    

    Star History

    Star History Chart


    Keywords / 关键词

    doubao api, 豆包 api, 豆包逆向, doubao reverse engineer, openai compatible api, free chatgpt api, free multimodal api, ai agent tools, doubao chat api, bytedance doubao, 豆包免费接口, text to image api free, text to video api free, text to music api, doubao2api, coze alternative, 免费大模型 api, 智能体多模态, deepseek agent tools, python openai server