# -*- coding: utf-8 -*-
|
import json
|
from pathlib import Path
|
from datetime import datetime, timedelta
|
from auto_media_publisher.utils.logger import get_logger
|
from auto_media_publisher.config.conf_video_mashup import *
|
from auto_media_publisher.generators.media_generator_base import MediaGenerator
|
from auto_media_publisher.config.conf_base import DATABASE_PATH,TASK_CONFIG_DIR,VIDEO_DIR_FINAL
|
from auto_media_publisher.utils.utils_database import media_update_task_done,publish_task_exists,publish_task_insert
|
|
|
class VideoGeneratorManual(MediaGenerator):
|
"""
|
手动地生成短视频,拷贝到 media_final / user_id / 目录下 之后。
|
要求:
|
1、每个视频要有三个文件:
|
mp4 文件、 png封面文件和json配置文件(可参考其他json)。
|
2、文件名 必须为 yyyymmddhhmmss.mp4 yyyymmddhhmmss.png yyyymmddhhmmss.json
|
如 20251009120000.mp4 20251009120000.png 20251009120000.json
|
|
本类执行的动作有两个:
|
0、 参考用户的配置文件中的user 的 enabled状态和 platform 的 enabled 状态。
|
1、 自动比对数据库中已有的任务清单,如果匹配上,就修改任务的视频状态为ready,后续上传进程会自动上传。
|
2、 如果任务时间,不在数据库中,可认为是临时的上传任务,因此添加到数据的任务表中,后续上传进程会自动上传。
|
|
"""
|
def __init__(self):
|
self.config_dir_path = Path(TASK_CONFIG_DIR)
|
self.media_dir_path = Path(VIDEO_DIR_FINAL)
|
self.db_path = DATABASE_PATH
|
self.logger = get_logger(self.__class__.__name__,"admin")
|
self.logger.info("VideoGeneratorManual started.")
|
|
def _get_avalible_media_times(self,user_id):
|
valid_times = []
|
now = datetime.now()
|
user_media_path = self.media_dir_path / user_id
|
|
for media_json in user_media_path.rglob("*.json"):
|
filename = media_json.stem # 去掉 .json 后缀
|
if not filename.isdigit() or len(filename) != 14:
|
print(f"非法文件名格式,跳过: {media_json.name}")
|
continue
|
|
try:
|
file_time = datetime.strptime(filename, "%Y%m%d%H%M%S")
|
except ValueError:
|
print(f"时间格式解析失败,跳过: {media_json.name}")
|
continue
|
|
# 如果不是将来的文件,跳过
|
if file_time <= now:
|
continue
|
|
base = media_json.with_suffix("") # 去掉 .json 的 Path
|
mp4_file = base.with_suffix(".mp4")
|
png_file = base.with_suffix(".png")
|
|
if mp4_file.exists() and png_file.exists():
|
formatted_time = file_time.strftime("%Y-%m-%d %H:%M:%S")
|
valid_times.append(formatted_time)
|
|
return valid_times
|
|
|
def run(self):
|
count = 0
|
count_new = 0
|
count_updated = 0
|
self.logger.info("VideoGeneratorManual 开始执行")
|
try:
|
for config_file in self.config_dir_path.rglob("*.json"):
|
try:
|
user_config = json.loads(config_file.read_text(encoding="utf-8"))
|
except Exception as e:
|
self.logger.warning(f"无法读取配置文件 {config_file.name}:{e}")
|
continue
|
|
if not user_config.get("enabled", True):
|
self.logger.info(f"跳过未启用用户:{config_file.name}")
|
continue
|
|
user_id = user_config.get("user")
|
user_media_times = self._get_avalible_media_times(user_id)
|
if not user_media_times :
|
continue
|
|
# 尝试给每一个video文件创建 N 个 task。 N的个数取决于 enabled 的platform数量。
|
for media_time in user_media_times:
|
|
proxy = user_config.get("proxy")
|
platforms = user_config.get("platforms", [])
|
|
for platform in platforms:
|
if not platform.get("enabled", True):
|
continue
|
|
platform_name = platform["name"]
|
generator_class = platform["media_generator"]
|
generator_args = platform["media_generator_args"]
|
generator_args_str = json.dumps(generator_args, ensure_ascii=False)
|
|
platform_days_ahead = platform["task_ahead_days"]
|
|
config_updated = self._get_config_updated(config_file)
|
|
future_limit = datetime.now() + timedelta(days=platform_days_ahead)
|
|
if not media_time < future_limit :
|
continue
|
|
existing = publish_task_exists(user_id, platform_name, media_time)
|
if existing:
|
task_id, old_hash, task_status = existing
|
media_update_task_done(task_id,datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
count_updated = count_updated +1
|
else:
|
publish_task_insert(user_id, platform_name, generator_class,generator_args_str,media_time, config_updated,proxy)
|
count_new =count_new+1
|
count += 1
|
except Exception as e:
|
self.logger.exception(f"VideoGeneratorManual 出错: {e}")
|
self.logger.info(f"累计检查 {count} 条任务。")
|
self.logger.info(f"{count_updated} 条任务已更新数据库")
|
self.logger.info(f"{count_new} 条任务已插入数据库")
|
|