agc_video.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. import configparser
  2. import glob
  3. import os
  4. import random
  5. import re
  6. import subprocess
  7. import sys
  8. import time
  9. import urllib.parse
  10. import json
  11. import requests
  12. from datetime import datetime, timedelta
  13. from urllib.parse import urlencode
  14. from common.sql_help import sqlHelp
  15. sys.path.append(os.getcwd())
  16. from common.db import MysqlHelper
  17. from common.material import Material
  18. from common import Common, Oss, Feishu, PQ
  19. from common.srt import SRT
  20. config = configparser.ConfigParser()
  21. config.read('./config.ini') # 替换为您的配置文件路径
  22. class AGC():
  23. """清除文件下所有mp4文件"""
  24. @classmethod
  25. def clear_mp4_files(cls, folder_path):
  26. # 获取文件夹中所有扩展名为 '.mp4' 的文件路径列表
  27. mp4_files = glob.glob(os.path.join(folder_path, '*.mp4'))
  28. if not mp4_files:
  29. return
  30. # 遍历并删除所有 .mp4 文件
  31. for mp4_file in mp4_files:
  32. os.remove(mp4_file)
  33. print(f"文件夹 '{folder_path}' 中的所有 .mp4 文件已清空。")
  34. """
  35. 站外视频拼接
  36. """
  37. @classmethod
  38. def zw_concatenate_videos(cls, videos, audio_duration, audio_video, platform, s_path, v_path, mark, v_oss_path):
  39. video_files = cls.concat_videos_with_subtitles(videos, audio_duration, platform, mark)
  40. Common.logger("video").info(f"{mark}的{platform}视频文件:{video_files}")
  41. if video_files == "":
  42. return ""
  43. print(f"{mark}的{platform}:开始拼接视频喽~~~")
  44. Common.logger("video").info(f"{mark}的{platform}:开始拼接视频喽~~~")
  45. if os.path.exists(s_path):
  46. # subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=11,Fontname=Hiragino Sans GB,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  47. subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=12,Fontname=wqy-zenhei,Bold=1,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  48. else:
  49. start_time = cls.seconds_to_srt_time(0)
  50. end_time = cls.seconds_to_srt_time(audio_duration)
  51. with open(s_path, 'w') as f:
  52. f.write(f"1\n{start_time} --> {end_time}\n分享、转发给群友\n")
  53. # subtitle_cmd = "drawtext=text='分享、转发给群友':fontsize=28:fontcolor=black:x=(w-text_w)/2:y=h-text_h-15"
  54. subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=12,Fontname=wqy-zenhei,Bold=1,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  55. # 背景色参数
  56. background_cmd = "drawbox=y=ih-65:color=yellow@1.0:width=iw:height=0:t=fill"
  57. VIDEO_COUNTER = 0
  58. FF_INPUT = ""
  59. FF_SCALE = ""
  60. FF_FILTER = ""
  61. ffmpeg_cmd = ["ffmpeg"]
  62. for videos in video_files:
  63. Common.logger("video").info(f"{mark}的{platform}视频:{videos[3]}")
  64. # 添加输入文件
  65. FF_INPUT += f" -i {videos[3]}"
  66. # 为每个视频文件统一长宽,并设置SAR(采样宽高比)
  67. FF_SCALE += f"[{VIDEO_COUNTER}:v]scale=320x480,setsar=1[v{VIDEO_COUNTER}];"
  68. # 为每个视频文件创建一个输入流,并添加到-filter_complex参数中
  69. FF_FILTER += f"[v{VIDEO_COUNTER}][{VIDEO_COUNTER}:a]"
  70. # 增加视频计数器
  71. VIDEO_COUNTER += 1
  72. # 构建最终的FFmpeg命令
  73. ffmpeg_cmd.extend(FF_INPUT.split())
  74. ffmpeg_cmd.extend(["-filter_complex", f"{FF_SCALE}{FF_FILTER}concat=n={VIDEO_COUNTER}:v=1:a=1[v][a]",
  75. "-map", "[v]", "-map", "[a]", v_path])
  76. # 多线程数
  77. num_threads = 4
  78. # 构建 FFmpeg 命令,生成视频
  79. ffmpeg_cmd_oss = [
  80. "ffmpeg",
  81. "-i", v_path, # 视频文件列表
  82. "-i", audio_video, # 音频文件
  83. "-c:v", "libx264", # 复制视频流
  84. "-c:a", "aac", # 编码音频流为AAC
  85. "-threads", str(num_threads),
  86. "-vf", f"{background_cmd},{subtitle_cmd}", # 添加背景色和字幕
  87. "-t", str(int(audio_duration)), # 保持与音频时长一致
  88. "-map", "0:v:0", # 映射第一个输入的视频流
  89. "-map", "1:a:0", # 映射第二个输入的音频流
  90. "-y", # 覆盖输出文件
  91. v_oss_path
  92. ]
  93. try:
  94. timeout_seconds = 25 * 60
  95. subprocess.run(ffmpeg_cmd, timeout=timeout_seconds)
  96. if os.path.isfile(v_path):
  97. subprocess.run(ffmpeg_cmd_oss, timeout=timeout_seconds)
  98. print("视频处理完成!")
  99. except subprocess.TimeoutExpired:
  100. print("视频处理超时,处理失败!")
  101. return ""
  102. except subprocess.CalledProcessError as e:
  103. print(f"视频处理失败:{e}")
  104. return ""
  105. print(f"{mark}的{platform}:视频拼接成功啦~~~")
  106. Common.logger("video").info(f"{mark}的{platform}:视频拼接成功啦~~~")
  107. return video_files
  108. """视频秒数转换"""
  109. @classmethod
  110. def seconds_to_srt_time(cls, seconds):
  111. hours = int(seconds // 3600)
  112. minutes = int((seconds % 3600) // 60)
  113. seconds = seconds % 60
  114. milliseconds = int((seconds - int(seconds)) * 1000)
  115. return f"{hours:02d}:{minutes:02d}:{int(seconds):02d},{milliseconds:03d}"
  116. """
  117. 获取视频文件的时长(秒)
  118. """
  119. @classmethod
  120. def get_video_duration(cls, video_file):
  121. result = subprocess.run(
  122. ["ffprobe", "-v", "error", "-show_entries", "format=duration",
  123. "-of", "default=noprint_wrappers=1:nokey=1", video_file],
  124. capture_output=True, text=True)
  125. return float(result.stdout)
  126. """计算需要拼接的视频"""
  127. @classmethod
  128. def concat_videos_with_subtitles(cls, videos, audio_duration, platform, mark):
  129. # 计算视频文件列表总时长
  130. if platform == "爆款" or platform == "跟随":
  131. total_video_duration = sum(cls.get_video_duration(video_file) for video_file in videos)
  132. else:
  133. total_video_duration = sum(cls.get_video_duration(video_file[3]) for video_file in videos)
  134. if platform == "爆款" or platform == "跟随":
  135. # 视频时长大于音频时长
  136. if total_video_duration > audio_duration:
  137. return videos
  138. # 计算音频秒数与视频秒数的比率,然后加一得到需要的视频数量
  139. video_audio_ratio = audio_duration / total_video_duration
  140. videos_needed = int(video_audio_ratio) + 2
  141. trimmed_video_list = videos * videos_needed
  142. return trimmed_video_list
  143. else:
  144. # 如果视频总时长小于音频时长,则不做拼接
  145. if total_video_duration < audio_duration:
  146. Common.logger("video").info(f"{mark}的{platform}渠道时长小于等于目标时长,不做视频拼接")
  147. return ""
  148. # 如果视频总时长大于音频时长,则截断视频
  149. trimmed_video_list = []
  150. remaining_duration = audio_duration
  151. for video_file in videos:
  152. video_duration = cls.get_video_duration(video_file[3])
  153. if video_duration <= remaining_duration:
  154. # 如果视频时长小于或等于剩余时长,则将整个视频添加到列表中
  155. trimmed_video_list.append(video_file)
  156. remaining_duration -= video_duration
  157. else:
  158. trimmed_video_list.append(video_file)
  159. break
  160. return trimmed_video_list
  161. """
  162. text文件没有则创建目录
  163. """
  164. @classmethod
  165. def bk_text_folders(cls, mark):
  166. oss_id = cls.random_id()
  167. v_text_url = config['PATHS']['VIDEO_PATH'] + mark + "/text/"
  168. if not os.path.exists(v_text_url):
  169. os.makedirs(v_text_url)
  170. # srt 文件地址
  171. text_path = v_text_url + mark + f"{str(oss_id)}.text"
  172. return text_path
  173. """
  174. 站内视频拼接
  175. """
  176. @classmethod
  177. def zn_concatenate_videos(cls, videos, audio_duration, audio_video, platform, s_path, mark, v_oss_path):
  178. text_ptah = cls.bk_text_folders(mark)
  179. video_files = cls.concat_videos_with_subtitles(videos, audio_duration, platform, mark)
  180. with open(text_ptah, 'w') as f:
  181. for file in video_files:
  182. f.write(f"file '{file}'\n")
  183. Common.logger("video").info(f"{mark}的{platform}视频文件:{video_files}")
  184. if video_files == "":
  185. return ""
  186. print(f"{mark}的{platform}:开始拼接视频喽~~~")
  187. Common.logger("video").info(f"{mark}的{platform}:开始拼接视频喽~~~")
  188. if os.path.exists(s_path):
  189. # subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=11,Fontname=Hiragino Sans GB,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  190. subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=12,Fontname=wqy-zenhei,Bold=1,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  191. else:
  192. start_time = cls.seconds_to_srt_time(0)
  193. end_time = cls.seconds_to_srt_time(audio_duration)
  194. with open(s_path, 'w') as f:
  195. f.write(f"1\n{start_time} --> {end_time}\n分享、转发给群友\n")
  196. # subtitle_cmd = "drawtext=text='分享、转发给群友':fontsize=28:fontcolor=black:x=(w-text_w)/2:y=h-text_h-15"
  197. subtitle_cmd = f"subtitles={s_path}:force_style='Fontsize=12,Fontname=wqy-zenhei,Bold=1,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000'"
  198. # 背景色参数
  199. background_cmd = "drawbox=y=ih-65:color=yellow@1.0:width=iw:height=0:t=fill"
  200. # 多线程数
  201. num_threads = 4
  202. # 构建 FFmpeg 命令,生成视频
  203. ffmpeg_cmd_oss = [
  204. "ffmpeg",
  205. "-f", "concat",
  206. "-safe", "0",
  207. "-i", f"{text_ptah}", # 视频文件列表
  208. "-i", audio_video, # 音频文件
  209. "-c:v", "libx264",
  210. "-c:a", "aac",
  211. "-threads", str(num_threads),
  212. "-vf", f"scale=320x480,{background_cmd},{subtitle_cmd}", # 添加背景色和字幕
  213. "-t", str(int(audio_duration)), # 保持与音频时长一致
  214. "-map", "0:v:0", # 映射第一个输入的视频流
  215. "-map", "1:a:0", # 映射第二个输入的音频流
  216. "-y", # 覆盖输出文件
  217. v_oss_path
  218. ]
  219. try:
  220. subprocess.run(ffmpeg_cmd_oss)
  221. print("视频处理完成!")
  222. if os.path.isfile(text_ptah):
  223. os.remove(text_ptah)
  224. except subprocess.CalledProcessError as e:
  225. print(f"视频处理失败:{e}")
  226. print(f"{mark}:视频拼接成功啦~~~")
  227. Common.logger("video").info(f"{mark}:视频拼接成功啦~~~")
  228. return v_oss_path
  229. """
  230. 获取视频时长
  231. """
  232. @classmethod
  233. def get_audio_duration(cls, video_url):
  234. ffprobe_cmd = [
  235. "ffprobe",
  236. "-i", video_url,
  237. "-show_entries", "format=duration",
  238. "-v", "quiet",
  239. "-of", "csv=p=0"
  240. ]
  241. output = subprocess.check_output(ffprobe_cmd).decode("utf-8").strip()
  242. return float(output)
  243. """
  244. 创建临时字幕
  245. """
  246. @classmethod
  247. def create_subtitle_file(cls, srt, s_path):
  248. with open(s_path, 'w') as f:
  249. f.write(srt)
  250. """
  251. 随机生成id
  252. """
  253. @classmethod
  254. def random_id(cls):
  255. now = datetime.now()
  256. rand_num = random.randint(10000, 99999)
  257. oss_id = "{}{}".format(now.strftime("%Y%m%d%H%M%S"), rand_num)
  258. return oss_id
  259. """
  260. 文件没有则创建目录
  261. """
  262. @classmethod
  263. def create_folders(cls, mark):
  264. oss_id = cls.random_id()
  265. video_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/"
  266. # srt 目录
  267. s_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/srt/"
  268. # oss 目录
  269. v_path_url = config['PATHS']['VIDEO_PATH'] + mark + "/oss/"
  270. if not os.path.exists(video_path_url):
  271. os.makedirs(video_path_url)
  272. if not os.path.exists(s_path_url):
  273. os.makedirs(s_path_url)
  274. if not os.path.exists(v_path_url):
  275. os.makedirs(v_path_url)
  276. # srt 文件地址
  277. s_path = s_path_url + mark + f"{str(oss_id)}.srt"
  278. # 最终生成视频地址
  279. v_path = v_path_url + mark + f"{str(oss_id)}.mp4"
  280. v_oss_path = v_path_url + mark + f"{str(oss_id)}oss.mp4"
  281. return s_path, v_path, video_path_url, v_oss_path
  282. """
  283. 获取未使用的数据
  284. """
  285. @classmethod
  286. def get_unique_uid_data(cls, data, count):
  287. unique_data_dict = {item['uid']: item for item in data}
  288. unique_data = list(unique_data_dict.values())
  289. if count >= len(unique_data):
  290. return unique_data
  291. else:
  292. selected_items = []
  293. selected_uids = set()
  294. while len(selected_items) < count:
  295. # 随机选择一个元素
  296. item = random.choice(unique_data)
  297. uid = item['uid']
  298. if uid not in selected_uids:
  299. # 如果该uid还未被选择过,则将该元素添加到选中项列表中,并记录已选择的uid
  300. selected_items.append(item)
  301. selected_uids.add(uid)
  302. return selected_items
  303. """
  304. 任务处理
  305. """
  306. @classmethod
  307. def video(cls, data, platform):
  308. mark_name = data['mark_name'] # 负责人
  309. if platform == "爆款":
  310. pq_ids = data["pq_id"]
  311. pq_ids_list = pq_ids.split(',') # 账号ID
  312. mark = data["mark"] # 标示
  313. feishu_id = data["feishu_id"] # 飞书文档ID
  314. video_call = data["video_call"] # 脚本sheet
  315. list_data = Material.get_allbk_data(feishu_id, video_call)
  316. if len(list_data) == 0:
  317. Feishu.bot('recommend', 'AGC完成通知', f'爆款任务数为0,不做拼接', mark, mark_name)
  318. return mark
  319. elif platform == "常规":
  320. pq_ids = data["pq_id"]# 账号ID
  321. pq_ids_list = pq_ids.split(',')
  322. mark = data["mark"]
  323. feishu_id = data["feishu_id"] # 飞书文档ID
  324. video_call = data["video_call"] # 脚本sheet
  325. video_count = data["video_count"]
  326. if int(video_count) == 0:
  327. Feishu.bot('recommend', 'AGC完成通知', f'常规任务数为{video_count},不做拼接', mark, mark_name)
  328. return mark
  329. data_list, videos_mark = Material.get_all_data(feishu_id, video_call, mark)
  330. list_data = cls.get_unique_uid_data(data_list, int(video_count))
  331. elif platform == "跟随":
  332. pq_ids = data["pq_id"]
  333. pq_ids_list = pq_ids.split(',') # 账号ID
  334. mark = data["mark"] # 标示
  335. feishu_id = data["feishu_id"] # 飞书文档ID
  336. video_call = data["video_call"]
  337. video_count = data["video_count"]
  338. if int(video_count) == 0:
  339. Feishu.bot('recommend', 'AGC完成通知', f'跟随任务数为{video_count},不做拼接', mark, mark_name)
  340. return mark
  341. data_list, videos = Material.get_all_data(feishu_id, video_call, mark)
  342. list_data = cls.get_unique_uid_data(data_list, int(video_count))
  343. s_path, v_path, video_path_url, v_oss_path = cls.create_folders(mark)
  344. count = 0
  345. while True:
  346. if count == len(list_data):
  347. break
  348. # for d_list in list_data:
  349. try:
  350. d_list = list_data[count]
  351. uid = d_list['uid'] # 音频id
  352. srt = d_list['text'] # srt
  353. cover = d_list['cover']
  354. audio_title = d_list['title']
  355. if srt:
  356. # 创建临时字幕文件
  357. cls.create_subtitle_file(srt, s_path)
  358. Common.logger("bk_video").info(f"S{mark} 文件目录创建成功")
  359. else:
  360. srt_new = SRT.getSrt(int(uid))
  361. if srt_new:
  362. current_time = datetime.now()
  363. formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
  364. values = [[mark, str(uid), srt_new, formatted_time]]
  365. random_wait_time = random.uniform(0.5, 2.5)
  366. time.sleep(random_wait_time)
  367. Feishu.insert_columns("IbVVsKCpbhxhSJtwYOUc8S1jnWb", "jd9qD9", "ROWS", 1, 2)
  368. time.sleep(random_wait_time)
  369. Feishu.update_values("IbVVsKCpbhxhSJtwYOUc8S1jnWb", "jd9qD9", "A2:Z2", values)
  370. # 创建临时字幕文件
  371. cls.create_subtitle_file(srt_new, s_path)
  372. Common.logger("video").info(f"S{mark}的{platform}渠道RT 文件目录创建成功")
  373. # 获取音频
  374. audio_video = PQ.get_audio_url(uid)
  375. Common.logger("video").info(f"{mark}的{platform}渠道获音频成功")
  376. audio_duration = cls.get_audio_duration(audio_video)
  377. Common.logger("video").info(f"{mark}的{platform}渠道获取需要拼接的音频秒数为:{audio_duration}")
  378. if platform != "常规":
  379. if platform == "爆款":
  380. videos = d_list['video']
  381. if ',' in videos:
  382. videos = str(videos).split(',')
  383. else:
  384. videos = [str(videos)]
  385. video_id = random.choice(videos)
  386. video_url = PQ.get_audio_url(video_id)
  387. download_video = Oss.download_url(video_url, video_path_url, str(video_id))
  388. if download_video:
  389. video_files = cls.zn_concatenate_videos(download_video, audio_duration, audio_video, platform,
  390. s_path, mark, v_oss_path)
  391. if os.path.isfile(v_oss_path):
  392. Common.logger("video").info(f"{mark}的{platform}渠道新视频生成成功")
  393. else:
  394. Common.logger("video").info(f"{mark}的{platform}渠道新视频生成失败")
  395. continue
  396. else:
  397. # chnnel_count = int(len(list_data)/2)
  398. channels = ["douyin", "kuaishou"]
  399. channel = random.choice(channels)
  400. user_id = sqlHelp.get_user_id(channel, mark)
  401. url_list, user = sqlHelp.get_url_list(user_id, mark, "35")
  402. videos = [list(item) for item in url_list]
  403. videos = Oss.get_oss_url(videos, video_path_url)
  404. video_files = cls.zw_concatenate_videos(videos, audio_duration, audio_video, platform, s_path, v_path,
  405. mark, v_oss_path)
  406. if video_files == "":
  407. Common.logger("video").info(f"{mark}的{platform}渠道使用拼接视频为空")
  408. continue
  409. if os.path.isfile(v_oss_path):
  410. Common.logger("video").info(f"{mark}的{platform}渠道新视频生成成功")
  411. else:
  412. Common.logger("video").info(f"{mark}的{platform}渠道新视频生成失败")
  413. continue
  414. # 随机生成视频oss_id
  415. oss_id = cls.random_id()
  416. Common.logger("video").info(f"{mark}的{platform}渠道上传到 OSS 生成视频id为:{oss_id}")
  417. oss_object_key = Oss.stitching_sync_upload_oss(v_oss_path, oss_id)
  418. status = oss_object_key.get("status")
  419. if status == 200:
  420. # 获取 oss 视频地址
  421. oss_object_key = oss_object_key.get("oss_object_key")
  422. Common.logger("video").info(f"{mark}的{platform}渠道拼接视频发送成功,OSS 地址:{oss_object_key}")
  423. time.sleep(10)
  424. if platform == "常规":
  425. # 已使用视频存入数据库
  426. Common.logger("video").info(f"{mark}的{platform}渠道开始已使用视频存入数据库")
  427. sqlHelp.insert_videoAudio(video_files, uid, platform, mark)
  428. Common.logger("video").info(f"{mark}的{platform}渠道完成已使用视频存入数据库")
  429. Common.logger("video").info(f"{mark}的{platform}渠道开始视频添加到对应用户")
  430. new_video_id, title = PQ.insert_piaoquantv(oss_object_key, audio_title, pq_ids_list, cover, uid)
  431. if new_video_id:
  432. Common.logger("video").info(f"{mark}的{platform}渠道视频添加到对应用户成功")
  433. if os.path.isfile(v_oss_path):
  434. os.remove(v_oss_path)
  435. if os.path.isfile(v_path):
  436. os.remove(v_path)
  437. if os.path.isfile(s_path):
  438. os.remove(s_path)
  439. # 清空所有mp4数据
  440. cls.clear_mp4_files(video_path_url)
  441. count += 1
  442. if mark_name == "穆新艺":
  443. sheet = '50b8a1'
  444. elif mark_name == "信欣":
  445. sheet = 'UyVK7y'
  446. elif mark_name == "范军":
  447. sheet = 'uP3zbf'
  448. elif mark_name == "鲁涛":
  449. sheet = 'iDTHt4'
  450. elif mark_name == "余海涛":
  451. sheet = 'R1jIeT'
  452. elif mark_name == "罗情":
  453. sheet = 'iuxfAt'
  454. current_time = datetime.now()
  455. formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
  456. if platform == "常规":
  457. third_chars = [j[2] for j in video_files]
  458. data = ",".join(third_chars)
  459. user_id = user
  460. else:
  461. user_id = video_id
  462. data = ''
  463. values = [[mark, str(uid), str(user_id), data, title, new_video_id, formatted_time]]
  464. Feishu.insert_columns("LAn9so7E0hxRYht2UMEcK5wpnMj", sheet, "ROWS", 1, 2)
  465. random_wait_time = random.uniform(0.5, 2.5)
  466. time.sleep(random_wait_time)
  467. Feishu.update_values("LAn9so7E0hxRYht2UMEcK5wpnMj", sheet, "A2:Z2", values)
  468. except Exception as e:
  469. Common.logger("bk_video").warning(f"{mark}的视频拼接失败:{e}\n")
  470. if os.path.isfile(v_oss_path):
  471. os.remove(v_oss_path)
  472. if os.path.isfile(v_path):
  473. os.remove(v_path)
  474. if os.path.isfile(s_path):
  475. os.remove(s_path)
  476. # 清空所有mp4数据
  477. cls.clear_mp4_files(video_path_url)
  478. continue
  479. if "-" in mark:
  480. name = mark.split("-")[0]
  481. else:
  482. name = mark
  483. Feishu.bot('recommend', 'AGC完成通知', f'今日{platform}任务拼接任务完成,共{count}条', name, mark_name)