核心及怎么运行

核心:本地运行 API 服务 → 调用豆包开放平台 / 火山引擎的文生图(Seedream)、文生视频(Seedance)能力 → 结果回写到本地

适用:本地开发、本地批量生成、本地存储、内网调用。

不适用:完全离线、无外网、模型权重私有化部署(官方暂不提供)。

安装准备

系统配置

CPU:4 核 +

内存:16GB+

存储:50GB+(模型 / 缓存 / 生成文件)

网络:可访问火山引擎 / 豆包开放平台

软件使用

Python 3.10–3.11(不会下载的看另一个CSDN博客sensen_kiss下载教程)

火山引擎 / 豆包开放平台账号(需实名认证、查看key-api)

申请 API 密钥(必做)

访问 火山引擎开放平台豆包开放平台
注册→实名认证→创建应用→获取 AccessKey (AK) / SecretKey (SK)。
开通:视觉生成(文生图 Seedream)、视频生成(Seedance) 服务。

Python 原生(推荐,轻量)

克隆 / 创建项目

mkdir doubao-local-multimodal
cd doubao-local-multimodal
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate

安装依赖

pip install volcengine fastapi uvicorn python-multipart pillow

编写本地服务(main.py

from fastapi import FastAPI, File, UploadFile
from volcengine.visual.VisualService import VisualService
import os
import uuid

app = FastAPI(title="豆包本地多模态服务")

# 初始化火山引擎视觉服务
visual_service = VisualService()
visual_service.set_ak("你的AK")
visual_service.set_sk("你的SK")

# 1. 文生图(Seedream)
@app.post("/generate-image")
def generate_image(prompt: str, size: str = "1024x1024", num: int = 1):
    req = {
        "req_key": "ai_image_generation",
        "prompt": prompt,
        "size": size,
        "num": num
    }
    resp = visual_service.ai_generate_image(req)
    # 保存到本地
    os.makedirs("output/images", exist_ok=True)
    result = []
    for i, img_url in enumerate(resp["data"]["image_urls"]):
        fname = f"output/images/{uuid.uuid4().hex}.png"
        # 下载并保存(略,用requests/urllib)
        result.append(fname)
    return {"status": "success", "files": result}

# 2. 文生视频(Seedance)
@app.post("/generate-video")
def generate_video(prompt: str, duration: int = 5, ratio: str = "9:16"):
    req = {
        "req_key": "ai_video_generation",
        "prompt": prompt,
        "duration": duration,
        "ratio": ratio
    }
    resp = visual_service.ai_generate_video(req)
    os.makedirs("output/videos", exist_ok=True)
    fname = f"output/videos/{uuid.uuid4().hex}.mp4"
    # 下载并保存(略)
    return {"status": "success", "file": fname}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

启动服务

uvicorn main:app --reload

查看效果

http://localhost:8000/docs

复制以上代码至浏览器地址栏查看

关键参数与优化(附完整可运行代码)

这部分重点补充所有可用参数优化生成效果的技巧,以及带完整下载逻辑的代码。

6.1 文生图(Seedream)全参数说明 + 优化代码

优化后的文生图代码(含下载 + 风格优化)

from fastapi import FastAPI, HTTPException
from volcengine.visual.VisualService import VisualService
import os
import uuid
import requests  # 补充下载依赖
import time

app = FastAPI(title="豆包本地多模态服务")

# 初始化视觉服务(用环境变量,更安全)
visual_service = VisualService()
visual_service.set_ak(os.getenv("DOUBAO_AK"))
visual_service.set_sk(os.getenv("DOUBAO_SK"))

# 确保输出目录存在
os.makedirs("output/images", exist_ok=True)
os.makedirs("output/videos", exist_ok=True)

# 文生图(完整优化版)
@app.post("/generate-image")
def generate_image(
    prompt: str,
    negative_prompt: str = "模糊、低分辨率、变形、锯齿、水印",  # 默认负面提示词
    size: str = "1024x1024",
    num: int = 1,
    style: str = "photorealistic",  # 写实风格(默认)
    resolution: str = "high"
):
    try:
        req = {
            "req_key": "ai_image_generation",
            "prompt": prompt,
            "negative_prompt": negative_prompt,
            "size": size,
            "num": num,
            "style": style,
            "resolution": resolution
        }
        # 调用API(部分接口需要轮询,因为生成需要时间)
        resp = visual_service.ai_generate_image(req)
        
        # 检查API返回是否成功
        if resp.get("code") != 10000:
            raise HTTPException(status_code=500, detail=f"API调用失败:{resp.get('msg')}")
        
        # 下载图片到本地
        result_files = []
        for i, img_url in enumerate(resp["data"]["image_urls"]):
            # 生成唯一文件名
            file_name = f"{uuid.uuid4().hex}.png"
            file_path = os.path.join("output/images", file_name)
            
            # 下载图片(加超时+重试)
            try:
                img_resp = requests.get(img_url, timeout=30)
                img_resp.raise_for_status()  # 抛出HTTP错误
                with open(file_path, "wb") as f:
                    f.write(img_resp.content)
                result_files.append(file_path)
            except Exception as e:
                raise HTTPException(status_code=500, detail=f"下载图片失败:{str(e)}")
        
        return {
            "status": "success",
            "files": result_files,
            "prompt": prompt,
            "style": style
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"生成图片失败:{str(e)}")

# Seedream支持的预设风格列表(直接复制用)
SUPPORTED_IMAGE_STYLES = [
    "photorealistic",  # 写实风格
    "watercolor",      # 水彩风格
    "oil_painting",    # 油画风格
    "cyberpunk",       # 赛博朋克风格
    "anime",           # 动漫风格
    "chinese_style",   # 国风风格
    "sketch",          # 素描风格
    "impressionism"    # 印象派风格
]

文生视频(Seedance)全参数说明 + 优化代码

# 文生视频(完整优化版,含轮询等待生成完成)
@app.post("/generate-video")
def generate_video(
    prompt: str,
    duration: int = 5,
    ratio: str = "9:16",
    style: str = "realistic"
):
    try:
        # 1. 提交视频生成任务(异步,需要轮询结果)
        submit_req = {
            "req_key": "ai_video_generation",
            "prompt": prompt,
            "duration": duration,
            "ratio": ratio,
            "style": style
        }
        submit_resp = visual_service.ai_generate_video(submit_req)
        
        # 检查提交是否成功
        if submit_resp.get("code") != 10000:
            raise HTTPException(status_code=500, detail=f"提交视频任务失败:{submit_resp.get('msg')}")
        
        task_id = submit_resp["data"]["task_id"]  # 获取任务ID
        print(f"视频生成任务已提交,ID:{task_id}")
        
        # 2. 轮询任务状态(每3秒查一次,最多等120秒)
        max_wait = 120  # 最大等待时间(秒)
        wait_interval = 3  # 轮询间隔(秒)
        elapsed = 0
        video_url = None
        
        while elapsed < max_wait:
            # 查询任务状态
            query_req = {
                "req_key": "ai_video_generation_query",
                "task_id": task_id
            }
            query_resp = visual_service.ai_generate_video_query(query_req)
            
            if query_resp["data"]["status"] == "success":
                video_url = query_resp["data"]["video_url"]
                break
            elif query_resp["data"]["status"] == "failed":
                raise HTTPException(status_code=500, detail=f"视频生成失败:{query_resp['data']['msg']}")
            
            # 未完成则等待
            time.sleep(wait_interval)
            elapsed += wait_interval
        
        if not video_url:
            raise HTTPException(status_code=500, detail="视频生成超时(超过120秒)")
        
        # 3. 下载视频到本地
        file_name = f"{uuid.uuid4().hex}.mp4"
        file_path = os.path.join("output/videos", file_name)
        
        try:
            video_resp = requests.get(video_url, timeout=60)
            video_resp.raise_for_status()
            with open(file_path, "wb") as f:
                f.write(video_resp.content)
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"下载视频失败:{str(e)}")
        
        return {
            "status": "success",
            "file": file_path,
            "task_id": task_id,
            "prompt": prompt
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"生成视频失败:{str(e)}")

效果优化技巧

提示词优化

文生图:主体+场景+风格+细节(例:“一只橘猫,躺在飘窗上,阳光洒在身上,写实风格,8K 分辨率,高清细节”);

文生视频:主体+动作+场景+时长(例:“一只柯基,在草地上追球,慢动作,5 秒,16:9 横屏”)。

负面提示词必加:避免模糊、低分辨率、变形、水印等问题,示例:模糊、低分辨率、锯齿、水印、拼接、扭曲

尺寸选择:文生图优先选 1024x1024(平衡效果和速度),2048x2048 需更高额度且生成慢。

常见问题(附具体排障步骤)

无法本地离线运行

原因:豆包多模态模型(Seedream/Seedance)的权重未开源,API 调用必须依赖外网访问火山引擎服务器;

排障

检查本地网络是否能访问火山引擎官网(https://www.volcengine.com/);

确认防火墙 / 代理未拦截 API 请求(可临时关闭代理测试);

若需内网使用:申请火山引擎 “专线接入”(企业级服务,需付费)。

密钥泄露 / 鉴权失败

表现:API 返回 “AK/SK 无效”“鉴权失败”“账号未实名认证”;

排障步骤:检查 AK/SK 是否正确(复制时不要多空格 / 少字符);

登录火山引擎控制台,确认:账号已完成实名认证(个人 / 企业均可,无认证无法调用 API);

视觉生成服务(Seedream/Seedance)已开通;账号有可用额度(免费额度可在 “费用中心” 查看,用完需充值);

若怀疑密钥泄露:立即在控制台重置 AK/SK,并更新本地代码 / 环境变量;

禁止硬编码密钥:必须用环境变量 / 配置文件(参考之前的环境变量代码)。

生成失败 / 返回空结果

表现:API 返回 “生成失败”“内容违规”“无结果”;

排障步骤

检查提示词是否合规(避免敏感内容,如暴力、色情、政治相关);

简化提示词(过长 / 过复杂的提示词易导致生成失败);

查看 API 返回的具体错误信息(代码中已捕获并返回,可在终端 / 接口返回中查看);

文生视频超时:缩短等待时间或检查网络(视频生成通常需要 30-60 秒)。

下载图片 / 视频失败

表现:接口返回 “下载图片失败”“连接超时”;

排障步骤

检查图片 / 视频 URL 是否有效(复制 URL 到浏览器,看能否直接打开);

增加下载超时时间(代码中已设为 30/60 秒,可适当延长);

检查本地磁盘是否有写入权限(output 目录是否能创建 / 写入文件);

若提示 “磁盘满”:清理磁盘空间,确保 output 目录有足够存储(视频文件通常 5-20MB / 个)。

Docker 部署后无法访问

表现:本地访问localhost:8000提示 “连接拒绝”;

排障步骤

检查 Docker 容器是否运行:docker ps(查看容器状态);

检查端口映射是否正确:docker run -p 8000:8000(宿主机端口:容器端口);

查看容器日志:docker logs 容器ID(排查代码报错);

确认容器内服务绑定 0.0.0.0(代码中 uvicorn 启动参数是 host="0.0.0.0")。

下一步(附具体对接方式)

需求:完全私有化、离线部署(模型权重本地运行)

现状:豆包官方暂未开放多模态模型(Seedream/Seedance)的权重下载,个人 / 中小团队无法实现完全离线部署;

对接方式

联系火山引擎企业服务:

官网入口:https://www.volcengine.com/product/visual(拉到最下方,点击 “咨询客服”);

对接内容:说明 “私有化部署 Seedream/Seedance 模型”,提供企业资质,洽谈合作(需付费,适合中大型企业);

替代方案(开源平替):

文生图:本地部署 Stable Diffusion(开源,完全离线,效果接近);

文生视频:本地部署 ModelScope 文生视频(阿里云开源,支持离线)。

需求:优化本地使用体验

可落地的优化方向

加前端页面(纯本地):用 Vue/React 写简单的 UI,调用本地 FastAPI 接口,无需登录,直接输入提示词生成;

批量生成脚本:写 Python 脚本,读取 txt 文件中的提示词列表,批量生成图片 / 视频并分类存储;

额度查询接口:新增接口,调用火山引擎费用中心 API,本地查看剩余额度;

错误重试机制:代码中增加自动重试(失败后重试 2-3 次),提升生成成功率。

需求:集成到本地应用 / 工具

对接方式

本地 Python 脚本调用:直接 import FastAPI 的客户端,或用 requests 调用本地接口;

本地软件集成:通过 HTTP 请求(如 C#/Java/Go)调用localhost:8000接口;

IDE 插件集成:基于 MCP 服务,集成到 VS Code/PyCharm,本地写代码时直接生成图片 / 视频。

注:

本文章有北京市一学校顺义学校初一年级学生制作

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐