职贝云数AI新零售门户

标题: 如何用 Multi-Agent 自动运营抖音账号:从脚本到内容闭环 [打印本页]

作者: aZgrMu    时间: 前天 07:40
标题: 如何用 Multi-Agent 自动运营抖音账号:从脚本到内容闭环
如今,让我们逐一完成这些智能体和组件。
环境搭建和依赖安装

首先,让我们设置开发环境并安装必要的依赖:
  1. # 首先,创建一个虚拟环境(引荐)# python -m venv douyin_agent_env# source douyin_agent_env/bin/activate  # Linux/Mac# .\douyin_agent_env\Scripts\activate  # Windows# 安装必要的包
  2. !pip install langchain openai python-dotenv moviepy pillow pandas matplotlib sqlite3 requests schedule
复制代码
接上去,创建一个 .env 文件来存储我们的API密钥和配置:
  1. OPENAI_API_KEY=your_openai_api_key_here
  2. DOUYIN_CLIENT_KEY=your_douyin_client_key_here
  3. DOUYIN_CLIENT_SECRET=your_douyin_client_secret_here
复制代码
基础组件完成

首先,让我们完成一些基础组件,这些将被一切智能体运用。
记忆系统(Memory System)

记忆系统允许智能体记住过去的交互、决策和结果,这对于保持分歧性和持续学习至关重要。
  1. from langchain.memory import ConversationBufferMemory, ConversationSummaryMemory
  2. from langchain.schema import BaseMessage
  3. import sqlite3
  4. from datetime import datetime
  5. import json
  6. from typing import List, Dict, Any
  7. classMemorySystem:def__init__(self, db_path:str="douyin_agent_memory.db"):
  8.         self.db_path = db_path
  9.         self._init_db()
  10.         self.conversation_memory = ConversationBufferMemory(return_messages=True)
  11.         self.summary_memory = ConversationSummaryMemory(llm=None)# 我们会在运用时设置LLMdef_init_db(self):"""初始化数据库表"""
  12.         conn = sqlite3.connect(self.db_path)
  13.         cursor = conn.cursor()# 创建内容历史表
  14.         cursor.execute('''
  15.         CREATE TABLE IF NOT EXISTS content_history (
  16.             id INTEGER PRIMARY KEY AUTOINCREMENT,
  17.             content_id TEXT UNIQUE,
  18.             content_type TEXT,
  19.             title TEXT,
  20.             description TEXT,
  21.             publish_date TIMESTAMP,
  22.             performance_data TEXT,
  23.             created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  24.         )
  25.         ''')# 创建决策记录表
  26.         cursor.execute('''
  27.         CREATE TABLE IF NOT EXISTS decision_history (
  28.             id INTEGER PRIMARY KEY AUTOINCREMENT,
  29.             agent_name TEXT,
  30.             decision_type TEXT,
  31.             decision_content TEXT,
  32.             context TEXT,
  33.             outcome TEXT,
  34.             timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  35.         )
  36.         ''')# 创建用户互动表
  37.         cursor.execute('''
  38.         CREATE TABLE IF NOT EXISTS user_interactions (
  39.             id INTEGER PRIMARY KEY AUTOINCREMENT,
  40.             interaction_type TEXT,
  41.             user_id TEXT,
  42.             content_id TEXT,
  43.             interaction_content TEXT,
  44.             response TEXT,
  45.             timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  46.         )
  47.         ''')
  48.         
  49.         conn.commit()
  50.         conn.close()defadd_conversation_message(self, message: BaseMessage):"""添加对话音讯到记忆"""
  51.         self.conversation_memory.chat_memory.add_message(message)defget_conversation_history(self)-> List[BaseMessage]:"""获取对话历史"""return self.conversation_memory.chat_memory.messages
  52.    
  53.     defrecord_content(self, content_id:str, content_type:str, title:str,
  54.                       description:str, publish_date: datetime =None,
  55.                       performance_data: Dict =None):"""记录内容发布信息"""
  56.         conn = sqlite3.connect(self.db_path)
  57.         cursor = conn.cursor()try:
  58.             cursor.execute('''
  59.             INSERT OR REPLACE INTO content_history
  60.             (content_id, content_type, title, description, publish_date, performance_data)
  61.             VALUES (?, ?, ?, ?, ?, ?)
  62.             ''',(
  63.                 content_id,
  64.                 content_type,
  65.                 title,
  66.                 description,
  67.                 publish_date.isoformat()if publish_date elseNone,
  68.                 json.dumps(performance_data)if performance_data elseNone))
  69.             conn.commit()except Exception as e:print(f"Error recording content: {e}")finally:
  70.             conn.close()defrecord_decision(self, agent_name:str, decision_type:str,
  71.                        decision_content:str, context: Dict =None,
  72.                        outcome:str=None):"""记录智能体决策"""
  73.         conn = sqlite3.connect(self.db_path)
  74.         cursor = conn.cursor()try:
  75.             cursor.execute('''
  76.             INSERT INTO decision_history
  77.             (agent_name, decision_type, decision_content, context, outcome)
  78.             VALUES (?, ?, ?, ?, ?)
  79.             ''',(
  80.                 agent_name,
  81.                 decision_type,
  82.                 decision_content,
  83.                 json.dumps(context)if context elseNone,
  84.                 outcome
  85.             ))
  86.             conn.commit()except Exception as e:print(f"Error recording decision: {e}")finally:
  87.             conn.close()defrecord_user_interaction(self, interaction_type:str, user_id:str,
  88.                                content_id:str, interaction_content:str,
  89.                                response:str=None):"""记录用户互动"""
  90.         conn = sqlite3.connect(self.db_path)
  91.         cursor = conn.cursor()try:
  92.             cursor.execute('''
  93.             INSERT INTO user_interactions
  94.             (interaction_type, user_id, content_id, interaction_content, response)
  95.             VALUES (?, ?, ?, ?, ?)
  96.             ''',(
  97.                 interaction_type,
  98.                 user_id,
  99.                 content_id,
  100.                 interaction_content,
  101.                 response
  102.             ))
  103.             conn.commit()except Exception as e:print(f"Error recording user interaction: {e}")finally:
  104.             conn.close()defget_content_history(self, limit:int=10)-> List[Dict]:"""获取内容历史"""
  105.         conn = sqlite3.connect(self.db_path)
  106.         cursor = conn.cursor()
  107.         
  108.         cursor.execute('''
  109.         SELECT content_id, content_type, title, description, publish_date, performance_data
  110.         FROM content_history
  111.         ORDER BY publish_date DESC
  112.         LIMIT ?
  113.         ''',(limit,))
  114.         
  115.         results = cursor.fetchall()
  116.         conn.close()
  117.         
  118.         content_list =[]for row in results:
  119.             content_list.append({'content_id': row[0],'content_type': row[1],'title': row[2],'description': row[3],'publish_date': row[4],'performance_data': json.loads(row[5])if row[5]elseNone})return content_list
  120.    
  121.     defget_top_performing_content(self, metric:str='view_count', limit:int=5)-> List[Dict]:"""获取表现最好的内容"""
  122.         conn = sqlite3.connect(self.db_path)
  123.         cursor = conn.cursor()
  124.         
  125.         cursor.execute('''
  126.         SELECT content_id, content_type, title, description, publish_date, performance_data
  127.         FROM content_history
  128.         WHERE performance_data IS NOT NULL
  129.         ORDER BY publish_date DESC
  130.         LIMIT 100
  131.         ''')
  132.         
  133.         results = cursor.fetchall()
  134.         conn.close()# 解析功能数据并排序
  135.         content_list =[]for row in results:
  136.             perf_data = json.loads(row[5])if row[5]else{}if metric in perf_data:
  137.                 content_list.append({'content_id': row[0],'content_type': row[1],'title': row[2],'description': row[3],'publish_date': row[4],'performance_data': perf_data,'metric_value': perf_data[metric]})# 按目的值排序
  138.         content_list.sort(key=lambda x: x['metric_value'], reverse=True)return content_list[:limit]
复制代码
工具库(Tool Library)

接上去,让我们创建一个工具库,包含各种智能体能够需求运用的工具:
  1. import requests
  2. import json
  3. from datetime import datetime, timedelta
  4. from typing import List, Dict, Any, Optional
  5. import os
  6. from dotenv import load_dotenv
  7. # 加载环境变量
  8. load_dotenv()classToolLibrary:def__init__(self):
  9.         self.douyin_api_base ="https://open.douyin.com"
  10.         self.douyin_client_key = os.getenv("DOUYIN_CLIENT_KEY")
  11.         self.douyin_client_secret = os.getenv("DOUYIN_CLIENT_SECRET")
  12.         self.access_token =None
  13.         self._refresh_access_token()def_refresh_access_token(self):"""刷新抖音API访问令牌"""
  14.         url =f"{self.douyin_api_base}/oauth/client_token/"
  15.         params ={"client_key": self.douyin_client_key,"client_secret": self.douyin_client_secret,"grant_type":"client_credential"}try:
  16.             response = requests.get(url, params=params)
  17.             response.raise_for_status()
  18.             data = response.json()if data.get("data"):
  19.                 self.access_token = data["data"].get("access_token")print("Access token refreshed successfully")else:print(f"Failed to refresh access token: {data}")except Exception as e:print(f"Error refreshing access token: {e}")defget_trending_topics(self, category:str="general")-> List[Dict]:"""获取当前抢手话题"""# 在实践运用中,这里可以衔接到抖音的热点API或第三方热点服务# 这里我们运用模拟数据作为示例
  20.         mock_trending_topics =[{"id":"1","title":"人工智能新打破","hot_value":9800000,"category":"科技"},{"id":"2","title":"健康饮食小贴士","hot_value":7500000,"category":"生活"},{"id":"3","title":"游览引荐地","hot_value":6200000,"category":"游览"},{"id":"4","title":"职场技能提升","hot_value":5800000,"category":"教育"},{"id":"5","title":"搞笑日常","hot_value":8900000,"category":"文娱"}]if category !="general":return[topic for topic in mock_trending_topics if topic["category"]== category]return mock_trending_topics
  21.    
  22.     defsearch_content_ideas(self, keyword:str, limit:int=10)-> List[Dict]:"""搜索内容创意"""# 在实践运用中,这里可以衔接到抖音的搜索API或第三方内容分析服务# 这里我们运用模拟数据作为示例
  23.         mock_ideas =[{"title":f"{keyword}的5个技巧","type":"教程","potential":"高"},{"title":f"{keyword}常见错误","type":"纠错","potential":"中"},{"title":f"{keyword}VS 其他方法","type":"对比","potential":"高"},{"title":f"我是如何学习{keyword}的","type":"个人阅历","potential":"中"},{"title":f"{keyword}的将来发展","type":"趋向分析","potential":"中高"}]return mock_ideas[:limit]defget_account_data(self)-> Dict:"""获取账号数据"""# 在实践运用中,这里应该调用抖音API# 这里我们运用模拟数据return{"fans_count":52000,"following_count":320,"total_likes":1200000,"total_views":45000000,"avg_views_per_video":150000,"avg_likes_per_video":4000,"avg_comments_per_video":150,"avg_shares_per_video":80}defget_video_performance(self, video_id:str)-> Dict:"""获取视频表现数据"""# 在实践运用中,这里应该调用抖音API# 这里我们运用模拟数据return{"video_id": video_id,"view_count":125000,"like_count":3200,"comment_count":180,"share_count":95,"completion_rate":0.68,# 完播率"average_watch_time":12.5,# 平均观看时长(秒)"publish_time":(datetime.now()- timedelta(days=3)).isoformat(),"performance_trend":"increasing"# 表现趋向}defget_comments(self, video_id:str, limit:int=50)-> List[Dict]:"""获取视频评论"""# 在实践运用中,这里应该调用抖音API# 这里我们运用模拟数据
  24.         mock_comments =[{"comment_id":"1","user_id":"user1","content":"这个视频太有用了!","like_count":45,"timestamp":"2023-10-01T10:30:00"},{"comment_id":"2","user_id":"user2","content":"请问第二步怎样做?","like_count":12,"timestamp":"2023-10-01T11:15:00"},{"comment_id":"3","user_id":"user3","content":"已收藏,当前渐渐看","like_count":8,"timestamp":"2023-10-01T12:45:00"},{"comment_id":"4","user_id":"user4","content":"不赞同你的观点,我以为...","like_count":23,"timestamp":"2023-10-01T14:20:00"},{"comment_id":"5","user_id":"user5","content":"能不能出一期更详细的?","like_count":31,"timestamp":"2023-10-01T16:05:00"}]return mock_comments[:limit]defreply_to_comment(self, comment_id:str, reply_content:str)->bool:"""回复评论"""# 在实践运用中,这里应该调用抖音APIprint(f"Replying to comment {comment_id}: {reply_content}")returnTrue# 假设回复成功defupload_video(self, video_path:str, title:str, description:str,
  25.                    tags: List[str]=None, publish_time: datetime =None)-> Optional[str]:"""上传视频(并可选地定时发布)"""# 在实践运用中,这里应该调用抖音API上传视频print(f"Uploading video: {title}")print(f"Description: {description}")print(f"Tags: {tags}")# 模拟生成一个视频ID
  26.         video_id =f"video_{datetime.now().strftime('%Y%m%d%H%M%S')}"return video_id
  27.    
  28.     defschedule_video_publish(self, video_id:str, publish_time: datetime)->bool:"""安排视频发布工夫"""# 在实践运用中,这里应该调用抖音APIprint(f"Scheduling video {video_id} to be published at {publish_time}")returnTrue# 假设操作成功
复制代码
智能体完成

如今,让我们末尾完成各个智能体。我们将运用LangChain框架来构建这些智能体。
创意总监Agent(Creative Director Agent)

创意总监Agent担任生成内容创意和选题方向。它会分析抢手话题、账号历史表现和粉丝兴味,提出有潜力的内容创意。
  1. from langchain.llms import OpenAI
  2. from langchain.prompts import PromptTemplate
  3. from langchain.chains import LLMChain
  4. from langchain.agents import AgentType, initialize_agent, Tool
  5. from typing import List, Dict, Any
  6. import json
  7. from datetime import datetime
  8. classCreativeDirectorAgent:def__init__(self, memory_system: MemorySystem, tool_library: ToolLibrary):
  9.         self.memory = memory_system
  10.         self.tools = tool_library
  11.         self.llm = OpenAI(temperature=0.7, max_tokens=2000)# 较高的温度以获得更多创意# 定义创意总监运用的工具
  12.         self.agent_tools =[
  13.             Tool(
  14.                 name="获取抢手话题",
  15.                 func=self.tools.get_trending_topics,
  16.                 description="获取当前抖音上的抢手话题,可用于内容创意"),
  17.             Tool(
  18.                 name="搜索内容创意",
  19.                 func=lambda keyword: json.dumps(self.tools.search_content_ideas(keyword), ensure_ascii=False),
  20.                 description="基于关键词搜索相关的内容创意"),
  21.             Tool(
  22.                 name="获取账号历史内容",
  23.                 func=lambda limit=10: json.dumps(self.memory.get_content_history(limit), ensure_ascii=False),
  24.                 description="获取账号历史发布的内容,用于参考和避免反复"),
  25.             Tool(
  26.                 name="获取高表现内容",
  27.                 func=lambda metric='view_count', limit=5: json.dumps(self.memory.get_top_performing_content(metric, limit), ensure_ascii=False),
  28.                 description="获取账号历史上表现最好的内容,分析成功要素")]# 创建创意总监Agent
  29.         self.agent = initialize_agent(
  30.             self.agent_tools,
  31.             self.llm,
  32.             agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
  33.             verbose=True)# 创意生成提示模板
  34.         self.creative_prompt = PromptTemplate(
  35.             input_variables=["account_data","content_objectives","constraints"],
  36.             template="""你是一位专业的抖音内容创意总监,担任为账号制定内容策略和生成创意选题。
  37.             
  38.             账号数据:
  39.             {account_data}
  40.             
  41.             内容目的:
  42.             {content_objectives}
  43.             
  44.             约束条件:
  45.             {constraints}
  46.             
  47.             请按照以下步骤停止思索和工作:
  48.             1. 首先,了解当前的抢手话题和趋向
  49.             2. 查看账号历史表现最好的内容,分析成功要素
  50.             3. 确保新创意与账号定位分歧,同时避免与历史内容反复
  51.             4. 生成5-7个有潜力的内容创意,每个创意包含:标题、类型、简要描画、预期效果、预估难度
  52.             
  53.             请以JSON格式前往你的创意建议。
  54.             """)defgenerate_content_ideas(self, content_objectives:str="添加粉丝互动和账号曝光",
  55.                               constraints:str="保持账号垂直范畴定位,每视频时长控制在15-60秒")-> List[Dict]:"""生成内容创意"""
  56.         account_data = self.tools.get_account_data()
  57.         account_data_str = json.dumps(account_data, ensure_ascii=False)
  58.         
  59.         prompt = self.creative_prompt.format(
  60.             account_data=account_data_str,
  61.             content_objectives=content_objectives,
  62.             constraints=constraints
  63.         )try:
  64.             result = self.agent.run(prompt)# 记录决策
  65.             self.memory.record_decision(
  66.                 agent_name="CreativeDirectorAgent",
  67.                 decision_type="content_ideas_generation",
  68.                 decision_content=result,
  69.                 context={"content_objectives": content_objectives,"constraints": constraints,"timestamp": datetime.now().isoformat()})# 尝试解析JSON结果try:
  70.                 ideas = json.loads(result)return ideas ifisinstance(ideas,list)else[ideas]except json.JSONDecodeError:# 假如不是有效的JSON,前往原始结果return[{"raw_result": result}]except Exception as e:print(f"Error generating content ideas: {e}")return[]defrefine_content_idea(self, idea: Dict, feedback:str)-> Dict:"""根据反馈优化内容创意"""
  71.         refine_prompt =f"""
  72.         原始创意:
  73.         {json.dumps(idea, ensure_ascii=False)}
  74.         
  75.         反馈意见:
  76.         {feedback}
  77.         
  78.         请根据反馈意见优化这个内容创意,保留其核心价值的同时,处理反馈中提到的成绩。
  79.         请以JSON格式前往优化后的创意。
  80.         """try:
  81.             result = self.agent.run(refine_prompt)# 记录决策
  82.             self.memory.record_decision(
  83.                 agent_name="CreativeDirectorAgent",
  84.                 decision_type="content_idea_refinement",
  85.                 decision_content=result,
  86.                 context={"original_idea": idea,"feedback": feedback,"timestamp": datetime.now().isoformat()})try:
  87.                 refined_idea = json.loads(result)return refined_idea
  88.             except json.JSONDecodeError:return{"raw_result": result,"original_idea": idea}except Exception as e:print(f"Error refining content idea: {e}")return idea
复制代码
剧本作家Agent(Script Writer Agent)

剧本作家Agent担任将创意转化为可拍摄的详细脚本,包括场景描画、台词、镜头建议等。
  1. from langchain.llms import OpenAI
  2. from langchain.prompts import PromptTemplate
  3. from langchain.chains import LLMChain
  4. from langchain.agents import AgentType, initialize_agent, Tool
  5. from typing import List, Dict, Any
  6. import json
  7. from datetime import datetime
  8. classScriptWriterAgent:def__init__(self, memory_system: MemorySystem, tool_library: ToolLibrary):
  9.         self.memory = memory_system
  10.         self.tools = tool_library
  11.         self.llm = OpenAI(temperature=0.8, max_tokens=3000)# 较高的温度以获得更有创意的脚本# 定义剧本作家运用的工具
  12.         self.agent_tools =[
  13.             Tool(
  14.                 name="获取高表现内容",
  15.                 func=lambda metric='view_count', limit=5: json.dumps(self.memory.get_top_performing_content(metric, limit), ensure_ascii=False),
  16.                 description="获取账号历史上表现最好的内容,分析其脚本结构和风格"),
  17.             Tool(
  18.                 name="搜索内容创意",
  19.                 func=lambda keyword: json.dumps(self.tools.search_content_ideas(keyword), ensure_ascii=False),
  20.                 description="基于关键词搜索相关的内容创意,为脚本提供更多灵感")]# 创建剧本作家Agent
  21.         self.agent = initialize_agent(
  22.             self.agent_tools,
  23.             self.llm,
  24.             agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
  25.             verbose=True)# 脚本写作提示模板
  26.         self.script_prompt = PromptTemplate(
  27.             input_variables=["content_idea","account_style","duration_constraint"],
  28.             template="""你是一位专业的抖音短视频编剧,擅长创作引人入胜、合适平台算法的短视频脚本。
  29.             
  30.             内容创意:
  31.             {content_idea}
  32.             
  33.             账号风格定位:
  34.             {account_style}
  35.             
  36.             时长约束:
  37.             {duration_constraint}
  38.             
  39.             请按照以下步骤停止思索和工作:
  40.             1. 首先,分析这个内容创意的核心价值和吸引点
  41.             2. 查看账号历史上表现最好的内容,分析其成功的脚本结构
  42.             3. 创作一个残缺的短视频脚本,包含以下元素:
  43.                - 视频概述:简要描画视频内容和目的
  44.                - 钩子设计:前3秒如何吸引观众留意力
  45.                - 详细脚本:按工夫线分解,包含场景、画面描画、台词/旁白、音乐/音效建议
  46.                - 互动设计:如何引导用户点赞、评论、分享
  47.                - 话题标签建议:相关的抢手话题和垂直范畴标签
  48.             
  49.             请以JSON格式前往你的脚本。
  50.             """)defwrite_script(self, content_idea: Dict,
  51.                     account_style:str="知识科普类,专业但不失兴趣,语速适中,画面明晰",
  52.                     duration_constraint:str="15-30秒")-> Dict:"""编写脚本"""
  53.         content_idea_str = json.dumps(content_idea, ensure_ascii=False)
  54.         
  55.         prompt = self.script_prompt.format(
  56.             content_idea=content_idea_str,
  57.             account_style=account_style,
  58.             duration_constraint=duration_constraint
  59.         )try:
  60.             result = self.agent.run(prompt)# 记录决策
  61.             self.memory.record_decision(
  62.                 agent_name="ScriptWriterAgent",
  63.                 decision_type="script_writing",
  64.                 decision_content=result,
  65.                 context={"content_idea": content_idea,"account_style": account_style,"duration_constraint": duration_constraint,"timestamp": datetime.now().isoformat()})# 尝试解析JSON结果try:
  66.                 script = json.loads(result)return script
  67.             except json.JSONDecodeError:# 假如不是有效的JSON,前往原始结果return{"raw_result": result}except Exception as e:print(f"Error writing script: {e}")return{}defrefine_script(self, script: Dict, feedback:str)-> Dict:"""根据反馈优化脚本"""
  68.         refine_prompt =f"""
  69.         原始脚本:
  70.         {json.dumps(script, ensure_ascii=False)}
  71.         
  72.         反馈意见:
  73.         {feedback}
  74.         
  75.         请根据反馈意见优化这个脚本,保留其核心价值的同时,处理反馈中提到的成绩。
  76.         请以JSON格式前往优化后的脚本。
  77.         """try:
  78.             result = self.agent.run(refine_prompt)# 记录决策
  79.             self.memory.record_decision(
  80.                 agent_name="ScriptWriterAgent",
  81.                 decision_type="script_refinement",
  82.                 decision_content=result,
  83.                 context={"original_script": script,"feedback": feedback,"timestamp": datetime.now().isoformat()})try:
  84.                 refined_script = json.loads(result)return refined_script
  85.             except json.JSONDecodeError:return{"raw_result": result,"original_script": script}except Exception as e:print(f"Error refining script: {e}")return script
复制代码
内容制造Agent(Content Producer Agent)

内容制造Agent担任根据脚本制造视频。它可以运用模板、素材库、文本转语音等工具来自动化生成视频。
  1. from langchain.llms import OpenAI
  2. from langchain.prompts import PromptTemplate
  3. from langchain.chains import LLMChain
  4. from langchain.agents import AgentType, initialize_agent, Tool
  5. from typing import List, Dict, Any, Optional
  6. import json
  7. from datetime import datetime
  8. import os
  9. from moviepy.editor import*from gtts import gTTS
  10. import requests
  11. from PIL import Image, ImageDraw, ImageFont
  12. classContentProducerAgent:def__init__(self, memory_system: MemorySystem, tool_library: ToolLibrary):
  13.         self.memory = memory_system
  14.         self.tools = tool_library
  15.         self.llm = OpenAI(temperature=0.3, max_tokens=1500)# 较低的温度以获得更准确的执行# 素材库途径
  16.         self.background_videos_path ="assets/background_videos"
  17.         self.music_path ="assets/music"
  18.         self.images_path ="assets/images"
  19.         self.output_path ="output/videos"# 确保目录存在for path in[self.background_videos_path, self.music_path, self.images_path, self.output_path]:
  20.             os.makedirs(path, exist_ok=True)# 定义内容制造运用的工具
  21.         self.agent_tools =[
  22.             Tool(
  23.                 name="文本转语音",
  24.                 func=self._text_to_speech,
  25.                 description="将文本转换为语音,参数为文本内容和可选的言语代码"),
  26.             Tool(
  27.                 name="搜索素材",
  28.                 func=self._search_materials,
  29.                 description="根据关键词搜索相关的素材(图片、视频、音乐)")]# 创建内容制造Agent
  30.         self.agent = initialize_agent(
  31.             self.agent_tools,
  32.             self.llm,
  33.             agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
  34.             verbose=True)# 视频制造计划提示模板
  35.         self.production_plan_prompt = PromptTemplate(
  36.             input_variables=["script","production_constraints"],
  37.             template="""你是一位专业的视频制造专家,担任根据脚本制定详细的视频制造计划。
  38.             
  39.             脚本内容:
  40.             {script}
  41.             
  42.             制造约束:
  43.             {production_constraints}
  44.             
  45.             请制定一个详细的视频制造计划,包含以下内容:
  46.             1. 素材需求清单:需求哪些图片、视频、音频素材
  47.             2. 视频结构:场景顺序、转场效果
  48.             3. 文本元素:需求添加的文本、字幕、标题,及其样式和地位
  49.             4. 音频计划:背景音乐、音效、旁白的安排
  50.             5. 制造步骤:详细的制造流程
  51.             
  52.             请以JSON格式前往你的制造计划。
  53.             """)def_text_to_speech(self, text:str, lang:str='zh')->str:"""将文本转换为语音"""try:
  54.             tts = gTTS(text=text, lang=lang, slow=False)
  55.             filename =f"temp_audio_{datetime.now().strftime('%Y%m%d%H%M%S')}.mp3"
  56.             filepath = os.path.join(self.output_path, filename)
  57.             tts.save(filepath)return filepath
  58.         except Exception as e:print(f"Error in text-to-speech: {e}")return""def_search_materials(self, keyword:str, material_type:str="all")-> List[str]:"""搜索素材(模拟函数)"""# 在实践运用中,这里可以衔接到素材库API或本地素材库# 这里我们前往模拟数据
  59.         mock_materials ={"background":["assets/background_videos/bg1.mp4","assets/background_videos/bg2.mp4"],"music":["assets/music/music1.mp3","assets/music/music2.mp3"],"image":["assets/images/img1.jpg","assets/images/img2.jpg"]}if material_type =="all":
  60.             results =[]for materials in mock_materials.values():
  61.                 results.extend(materials)return results
  62.         
  63.         return mock_materials.get(material_type,[])def_create_text_image(self, text:str, size:tuple=(1080,1920),
  64.                           font_size:int=80, text_color:tuple=(255,255,255),
  65.                           bg_color:tuple=(0,0,0,180))->str:"""创建包含文本的图片"""try:# 创建透明背景
  66.             img = Image.new('RGBA', size, bg_color)
  67.             draw = ImageDraw.Draw(img)# 加载字体(这里运用系统默许字体,实践运用中可以指定字体文件)try:
  68.                 font = ImageFont.truetype("arial.ttf", font_size)except:
  69.                 font = ImageFont.load_default()# 计算文本地位(居中)
  70.             text_bbox = draw.textbbox((0,0), text, font=font)
  71.             text_width = text_bbox[2]- text_bbox[0]
  72.             text_height = text_bbox[3]- text_bbox[1]
  73.             x =(size[0]- text_width)//2
  74.             y =(size[1]- text_height)//2# 绘制文本
  75.             draw.text((x, y), text, font=font, fill=text_color)# 保存图片
  76.             filename =f"text_image_{datetime.now().strftime('%Y%m%d%H%M%S')}.png"
  77.             filepath = os.path.join(self.output_path, filename)
  78.             img.save(filepath)return filepath
  79.         except Exception as e:print(f"Error creating text image: {e}")return""defcreate_production_plan(self, script: Dict,
  80.                               production_constraints:str="运用现有的素材库,保持竖屏9:16格式,视频明晰流利")-> Dict:"""创建视频制造计划"""
  81.         script_str = json.dumps(script, ensure_ascii=False)
  82.         
  83.         prompt = self.production_plan_prompt.format(
  84.             script=script_str,
  85.             production_constraints=production_constraints
  86.         )try:
  87.             result = self.agent.run(prompt)# 记录决策
  88.             self.memory.record_decision(
  89.                 agent_name="ContentProducerAgent",
  90.                 decision_type="production_plan_creation",
  91.                 decision_content=result,
  92.                 context={"script": script,"production_constraints": production_constraints,"timestamp": datetime.now().isoformat()})# 尝试解析JSON结果try:
  93.                 plan = json.loads(result)return plan
  94.             except json.JSONDecodeError:# 假如不是有效的JSON,前往原始结果return{"raw_result": result}except Exception as e:print(f"Error creating production plan: {e}")return{}defproduce_video(self, script: Dict, production_plan: Dict =None)-> Optional[str]:"""根据脚本和制造计划制造视频"""# 假如没有提供制造计划,先创建一个ifnot production_plan:
  95.             production_plan = self.create_production_plan(script)try:# 这是一个简化的视频制造流程# 在实践运用中,你能够需求根据脚本和制造计划的详细结构来完成# 1. 预备素材# 这里我们运用一些简单的素材作为示例
  96.             bg_video_path = os.path.join(self.background_videos_path,"sample_bg.mp4")# 假如没有示例背景视频,创建一个简单的纯色背景ifnot os.path.exists(bg_video_path):# 创建一个5秒的黑色背景视频
  97.                 bg_clip = ColorClip(size=(1080,1920), color=(0,0,0
复制代码





欢迎光临 职贝云数AI新零售门户 (https://www.taojin168.com/cloud/) Powered by Discuz! X3.5