wangzhibo
2025-07-30 245253cd9e0ebaad3b9b4efbfae8c0e3090afc9b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# -*- 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} 条任务已插入数据库")