从传统到智能:构建丽江客栈抖音视频生成MCP服务器的完整实践

抖音视频分镜脚本

分镜编号时长画面内容拍摄要点对话/旁白视觉效果
A-10:00-0:10丽江古城全景航拍,阳光洒在纳西族传统建筑上,镜头缓缓推进到一家特色客栈门口使用无人机高空俯拍,保持稳定匀速推进,选择黄金时段拍摄(画外音)'在丽江,传统与现代的碰撞,会擦出怎样的火花?'淡入开场,配悠扬的民族音乐
A-20:10-0:20客栈老板(舅舅)在庭院里手写分镜脚本,表情苦恼,桌上堆满草稿纸中景平拍,突出人物表情和杂乱桌面,自然光拍摄(舅舅叹气)'每天写脚本太费时间了...'镜头轻微晃动表现烦恼情绪
B-10:20-0:30电脑屏幕特写,显示代码运行过程,AI正在自动生成分镜表格低角度特写屏幕,键盘敲击声同期录音(键盘声+画外音)'用AI技术,1分钟搞定3小时的工作!'代码快速滚动特效,配科技感音效
B-20:30-0:40分屏画面:左侧传统手工制作视频过程,右侧AI自动生成视频过程固定机位对比拍摄,保持两侧构图对称(画外音)'传统VS智能,你pick哪种方式?'左右分屏转场特效
C-10:40-0:50手机屏幕显示Claude Desktop界面,AI助手正在调用MCP服务器生成视频手持拍摄第一人称视角,突出手机操作过程(点击声+AI语音)'正在为您生成丽江客栈宣传视频...'手机界面放大特效
C-20:50-1:00客栈实景与AI生成视频画面无缝切换,展示不同风格效果相同构图拍摄实景和虚拟画面,便于后期匹配(画外音)'AI不仅能理解需求,还能保持风格统一!'流畅的变形转场效果
D-11:00-1:10舅舅惊喜地看着电脑上生成的视频成品,竖起大拇指从电脑屏幕拉出到人物中景,捕捉自然表情(舅舅笑)'这下可以专心经营客栈啦!'画面调亮表现喜悦情绪
D-21:10-1:20客栈门口挂上'智能体验客栈'招牌,游客进出热闹场景广角镜头拍摄全景,捕捉人物自然互动(画外音)'科技让传统文化焕发新生!点击了解AI视频生成方案~'结尾弹出联系方式字幕

作为一名AI工程师,最近为舅舅的丽江客栈项目开发了一套完整的抖音视频生成系统。这个项目不仅让我深度体验了从传统工具到AI智能化的技术演进,更让我见证了MCP(Model Context Protocol)服务器在实际场景中的强大能力。

今天想和大家分享这个完整的技术实践过程,从最初的需求分析到最终的智能化解决方案,以及其中踩过的坑和收获的经验。

项目背景:为什么要做这个系统?

故事要从我舅舅的丽江客栈说起。作为一个传统的纳西族建筑改造项目,客栈需要通过短视频来展示其独特的文化魅力和现代化改造过程。但问题来了:

  1. 内容创作效率低:手工制作分镜脚本耗时且专业要求高
  2. 视觉一致性难保证:多个分镜的视觉风格容易不统一
  3. 技术门槛高:传统视频制作需要专业技能
  4. 远程协作困难:我在北京,舅舅在丽江,沟通成本高

作为一个技术人,我的第一反应是:这些问题都可以用AI来解决

系统架构演进:从1.0到3.0的跨越

1.0版本:传统正则解析时代

最初的想法很简单:写一个脚本来解析Markdown博文中的分镜表格,然后调用DALL-E生成对应的图片。

# 传统的正则表达式解析
def parse_scene_table_regex(content: str) -> List[Dict]:
    table_pattern = r'\|\s*\*\*([A-F]-\d+)\*\*\s*\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|([^|]+)\|'
    matches = re.findall(table_pattern, content, re.MULTILINE)
    # ... 复杂的正则处理逻辑

这个版本的问题很快就暴露出来了:

  • 解析成功率只有60-70%:表格格式稍有变化就失效
  • 扩展性差:添加新的分镜格式需要重写正则
  • 错误处理复杂:很难定位解析失败的具体原因

2.0版本:AI智能解析的觉醒

认识到正则表达式的局限性后,我开始思考:既然AI能理解自然语言,为什么不让它来理解分镜表格呢?

class SmartBlogParser:
    def __init__(self):
        self.client = OpenAI(
            api_key=os.getenv("DEEPSEEK_API_KEY"),
            base_url="https://api.deepseek.com"
        )
    
    def parse_with_ai(self, content: str) -> List[SceneData]:
        prompt = self._generate_scene_analysis_prompt(has_table=self._detect_table(content))
        response = self._call_deepseek_api(prompt.format(content=content))
        return self._parse_ai_response(response)

关键的突破在于设计了自适应的Prompt模板

def _generate_scene_analysis_prompt(self, has_table: bool) -> str:
    if has_table:
        return """# 分镜表格提取专家
        
你是一个专业的视频分镜表格解析专家。请精确提取博文中的分镜表格信息。

## 输出格式
请严格按照以下JSON格式输出:
{
  "extraction_method": "table_parsing",
  "scenes": [...]
}

## 博文内容
{content}"""
    else:
        return """# 智能分镜生成专家
        
你是一个专业的视频分镜创作专家。请根据博文内容智能生成8-12个分镜脚本。

## 分镜设计原则
- 开头:引人注目的开场(1-2个分镜)
- 主体:内容展开和重点阐述(6-8个分镜)
- 结尾:总结或行动号召(1-2个分镜)

{content}"""

这个版本的提升非常显著:

  • 解析成功率提升到95-99%
  • 支持内容生成:不仅能解析现有表格,还能基于内容创建新分镜
  • 智能化程度高:能理解上下文,生成更合理的分镜序列

3.0版本:MCP服务器的革命性升级

虽然2.0版本已经很强大,但我发现了一个更有趣的可能性:如果能让Claude Desktop直接调用这些功能,岂不是能创造出更好的用户体验?

这就是MCP(Model Context Protocol)服务器的用武之地。MCP是Anthropic推出的协议,允许AI助手与外部工具无缝集成。

MCP服务器实现:双协议架构

我设计了一个支持双协议的MCP服务器架构:

STDIO MCP服务器(Claude Desktop集成)

from fastmcp import FastMCP

mcp = FastMCP("Douyin Scene Generator")

@mcp.tool()
def parse_scenes_with_ai(blog_path: str, parser_type: str = "hybrid") -> Dict[str, Any]:
    """使用AI智能解析博文中的分镜表格信息"""
    try:
        if parser_type == "smart":
            parser = SmartBlogParser()
        elif parser_type == "hybrid":
            parser = HybridBlogParser(use_ai_fallback=True, use_ai_enhancement=True)
        else:
            parser = BlogParser()
        
        metadata, scenes = parser.parse_blog_post(blog_path)
        # ... 处理逻辑
        
        return {
            "success": True,
            "total_scenes": len(scene_list),
            "scenes": scene_list,
            "parser_used": parser_type
        }
    except Exception as e:
        return {"success": False, "error": f"AI解析分镜失败: {str(e)}"}

HTTP MCP服务器(Web API集成)

为了提供更好的扩展性,我还实现了HTTP版本:

from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse

app = FastAPI(title="Douyin Scene Generator MCP Server")

@app.post("/tools/call")
async def call_tool(request: ToolCallRequest):
    """统一的工具调用接口"""
    tool_name = request.tool_name
    
    if tool_name == "parse_scenes_with_ai":
        return await _parse_scenes_with_ai(**request.parameters)
    elif tool_name == "generate_scene_images":
        return await _generate_scene_images(**request.parameters)
    # ... 其他工具
    
    raise HTTPException(status_code=404, detail=f"工具 {tool_name} 不存在")

@app.get("/tools/batch_process/stream")
async def batch_process_stream(blog_dir: str, pattern: str = "**/*index.md"):
    """流式批量处理接口"""
    return StreamingResponse(
        _batch_process_blogs_stream(blog_dir, pattern),
        media_type="text/event-stream"
    )

核心功能模块设计

1. 智能内容提取器

class OptimizedContentExtractor:
    def extract_content_for_ai_analysis(self, blog_path: str) -> Dict[str, Any]:
        """为AI分析提取和预处理博文内容"""
        content = self._read_blog_file(blog_path)
        metadata = self._extract_metadata(content)
        
        # 智能检测内容类型
        has_scene_table = self._detect_scene_table(content)
        content_type = self._analyze_content_type(content, metadata)
        
        # 生成适配的Prompt模板
        prompt_template = self._generate_scene_analysis_prompt(has_scene_table)
        
        return {
            "success": True,
            "content": self._clean_content_for_ai(content),
            "metadata": metadata,
            "has_scene_table": has_scene_table,
            "content_type": content_type,
            "recommended_prompt": prompt_template,
            "analysis_suggestions": self._generate_analysis_suggestions(content_type)
        }

2. 多模式解析器

系统支持三种解析模式:

  • Regex模式:传统正则表达式,适用于格式严格的表格
  • Smart模式:纯AI解析,适用于复杂或非标准格式
  • Hybrid模式:智能混合,先正则后AI,兼顾效率和准确性
class HybridBlogParser:
    def __init__(self, use_ai_fallback=True, use_ai_enhancement=True):
        self.regex_parser = BlogParser()
        self.smart_parser = SmartBlogParser()
        self.use_ai_fallback = use_ai_fallback
        self.use_ai_enhancement = use_ai_enhancement
    
    def parse_blog_post(self, blog_path: str) -> Tuple[Dict, List[SceneData]]:
        # 先尝试正则解析
        metadata, scenes = self.regex_parser.parse_blog_post(blog_path)
        
        # 如果失败或结果不理想,使用AI增强
        if not scenes and self.use_ai_fallback:
            _, scenes = self.smart_parser.parse_blog_post(blog_path)
        
        if scenes and self.use_ai_enhancement:
            scenes = self.smart_parser.enhance_scenes_with_ai(scenes)
        
        return metadata, scenes

3. 图片生成管理器

class ImageManager:
    def generate_scene_image(self, scene: SceneData, blog_metadata: Dict) -> Optional[str]:
        """为单个分镜生成图片"""
        prompt = self._build_image_prompt(scene, blog_metadata)
        
        try:
            response = self.client.images.generate(
                model="dall-e-3",
                prompt=prompt,
                size=self.config.get("size", "1024x1024"),
                quality=self.config.get("quality", "standard"),
                n=1
            )
            
            image_url = response.data[0].url
            local_path = self._download_and_save_image(image_url, scene.scene_id, blog_metadata)
            
            return local_path
        except Exception as e:
            logger.error(f"生成图片失败 (场景 {scene.scene_id}): {e}")
            return None
    
    def _build_image_prompt(self, scene: SceneData, metadata: Dict) -> str:
        """构建图片生成的提示词"""
        base_prompt = f"""
        场景内容:{scene.content}
        拍摄要点:{scene.shooting_tips}
        视觉效果:{scene.visual_effects}
        
        风格要求:
        - 纳西族传统建筑风格
        - 现代化改造元素
        - 温暖的人文气息
        - 高质量摄影风格
        """
        
        return self._refine_prompt_for_dalle(base_prompt)

项目管理:Poetry统一化

为了简化项目管理,我创建了一个Poetry管理器:

class PoetryManager:
    def __init__(self):
        self.project_root = Path(__file__).parent
        self.tools_dir = self.project_root
    
    def start_stdio_server(self):
        """启动STDIO MCP服务器"""
        print("🚀 启动STDIO MCP服务器...")
        subprocess.run([
            "poetry", "run", "python", "-m", "douyin_generator.cli", "--mcp-server"
        ], cwd=self.tools_dir)
    
    def start_http_server(self, port=8000):
        """启动HTTP MCP服务器"""
        print(f"🌐 启动HTTP MCP服务器 (端口 {port})...")
        subprocess.run([
            "poetry", "run", "uvicorn", "mcp_server.http_server:app",
            "--host", "0.0.0.0", "--port", str(port), "--reload"
        ], cwd=self.tools_dir)

实际使用体验

Claude Desktop集成

配置文件 claude_desktop_config.json

{
  "mcpServers": {
    "douyin-scene-generator": {
      "command": "/Users/polly/Downloads/Sublime_Workspace/Zola_Workspace/www.polly.com/tools/mcp_server/start_server.sh"
    }
  }
}

使用时只需在Claude中说:

"帮我解析这个博文的分镜表格:/path/to/blog.md,使用智能模式"

Claude会自动调用相应的MCP工具,返回解析结果。

HTTP API调用

# 健康检查
curl http://localhost:8000/health

# 获取工具列表
curl http://localhost:8000/tools

# AI解析博文
curl -X POST http://localhost:8000/tools/call \
  -H "Content-Type: application/json" \
  -d '{
    "tool_name": "parse_scenes_with_ai",
    "parameters": {
      "blog_path": "/path/to/blog.md",
      "parser_type": "hybrid"
    }
  }'

性能优化与架构思考

解析性能对比

经过实际测试,不同解析模式的性能表现:

解析模式成功率平均耗时适用场景
Regex60-70%0.1s标准格式表格
Smart95-99%2-5s复杂格式、内容生成
Hybrid90-95%0.5-3s平衡效率与准确性

架构优化方向

在开发过程中,我思考了一个重要的架构问题:是否应该将所有AI推理都交给Claude客户端,而让MCP服务器专注于数据处理?

当前架构:

Claude Client -> Claude Desktop -> MCP Server -> SmartBlogParser -> DeepSeek API

优化后架构:

Claude Client -> 统一LLM推理 -> Claude Desktop -> MCP Server (纯数据处理)

这个优化的核心思想是回归MCP协议的本质:让AI负责推理,让工具负责数据处理。具体实施方案包括:

  1. Prompt工程统一化:将AI推理能力从MCP Server剥离
  2. 工具职责重新设计:专注于内容提取、格式转换、数据验证
  3. 统一的错误处理:简化调试和维护流程

踩过的坑与解决方案

1. Poetry环境管理

问题:Claude Desktop找不到poetry命令

spawn poetry ENOENT

解决方案:使用绝对路径和启动脚本

#!/bin/bash
export PATH="/Users/polly/.local/bin:$PATH"
cd "/path/to/project/tools"
poetry install --no-dev
exec poetry run python -m mcp_server.server

2. AI API调用优化

问题:DeepSeek API调用偶尔超时或返回格式不正确

解决方案:增加重试机制和响应验证

def _call_deepseek_api_with_retry(self, prompt: str, max_retries=3) -> str:
    for attempt in range(max_retries):
        try:
            response = self.client.chat.completions.create(
                model="deepseek-chat",
                messages=[{"role": "user", "content": prompt}],
                temperature=0.1,
                timeout=30
            )
            
            result = response.choices[0].message.content
            # 验证JSON格式
            json.loads(result)
            return result
            
        except Exception as e:
            if attempt == max_retries - 1:
                raise e
            time.sleep(2 ** attempt)  # 指数退避

3. 跨平台兼容性

问题:macOS和Linux的路径处理差异

解决方案:使用pathlib统一路径处理

from pathlib import Path

def get_project_root() -> Path:
    """获取项目根目录,跨平台兼容"""
    current_file = Path(__file__).resolve()
    # 向上查找包含pyproject.toml的目录
    for parent in current_file.parents:
        if (parent / "pyproject.toml").exists():
            return parent
    return current_file.parent

项目成果与价值体现

定量指标

  • 开发效率提升:分镜制作时间从2-3小时缩短到10-15分钟
  • 解析准确率:从60%提升到95%以上
  • 功能丰富度:从单一解析扩展到解析+生成+增强的完整工具链
  • 用户体验:从命令行工具升级到自然语言交互

技术价值

  1. MCP协议实践:深度体验了MCP服务器的开发和部署
  2. AI工程应用:将大模型能力有效集成到实际业务场景
  3. 架构设计思考:从单体应用到分布式服务的演进思路
  4. 跨平台兼容:Poetry + Docker的现代化Python项目管理

业务价值

  1. 降低门槛:非技术人员也能快速生成专业的视频内容
  2. 保证质量:AI确保了视觉风格的一致性和专业性
  3. 提升效率:自动化工作流大幅提升内容创作效率
  4. 文化传承:通过技术手段更好地展示传统纳西族建筑文化

未来展望与持续优化

短期计划

  1. 多媒体支持:扩展到音频生成和视频剪辑
  2. 模板系统:为不同类型的内容提供预设模板
  3. 批量处理优化:支持大规模并行处理
  4. 用户界面:开发Web界面,降低使用门槛

长期愿景

  1. 智能化升级:集成更多AI能力,如语音合成、视频剪辑
  2. 平台扩展:支持更多短视频平台的特定需求
  3. 生态建设:开源项目,建立开发者社区
  4. 商业化探索:为类似需求的企业提供SaaS服务

总结反思

这个项目让我深刻体会到了AI技术在实际应用中的巨大潜力。从最初的简单需求到最终的完整解决方案,每一步都充满了挑战和惊喜。

技术层面,我学会了如何设计一个真正实用的AI工具:不是简单地调用API,而是要深入理解业务需求,设计合适的架构,优化用户体验。

业务层面,这个项目展示了技术如何真正赋能传统行业:通过AI让复杂的视频制作变得简单,让专业的内容创作变得普及。

个人成长,这次实践让我对MCP协议、AI工程、项目管理都有了更深的理解。更重要的是,我学会了如何将技术与人文关怀结合,用代码传递温暖。

最后想说的是,技术的价值不在于它有多么复杂,而在于它能解决多少实际问题,能为多少人带来便利。这个丽江客栈的抖音视频生成系统,或许就是一个小小的例子,展示了AI如何让生活变得更美好。

如果你也在思考如何将AI技术应用到实际场景中,希望这个项目的经验能给你一些启发。记住,最好的技术,是那些让人忘记技术存在的技术。


项目源码已开源,欢迎Star和Fork:https://github.com/polly/lijiang-ai-mcp-server

如果你对MCP服务器开发或AI工程实践有兴趣,欢迎在评论区交流讨论!

留言与讨论