Browse Source

增加ai标题

zhangyong 9 months ago
parent
commit
97be4c326b

+ 73 - 0
common/gpt4o_help.py

@@ -0,0 +1,73 @@
+import json
+import time
+
+import requests
+
+
+
+class GPT4o():
+    @classmethod
+    def get_ai_title(cls, old_title):
+        content = '''
+                User: 请针对微信平台视频类小程序场景,面向人群是中国中老年人,在单聊、群聊场景,对不同视频内容原标题,在分享卡片上预览的标题进行优化。优化目标是提高这个场景下的视频卡片点击率。要求优化过程综合考虑下面的要求:
+
+                第一:根据下面的优秀标题示例,总结优秀标题特点,生成一个新标题。
+                此视频献给四零后,看完感触颇多!
+                🔴88岁三胞胎兄妹表演《沙家浜》,开口惊艳全场!
+                50年前毛主席就告诫了,今天一一验证!苦的还是老百姓
+                🔴十分通透的一段话,写得太棒了,请朋友们收好!
+                🏆那个部位最先知道脑梗呢
+                ✿这才叫老同学聚会,到了这个年纪,还能聚在一起真不容易
+                活久未见的照片,历史书上看不到,了解那些鲜为人知的过去
+                🚩中国人正在丢失的这几样东西!都转发看看吧~
+                🔥热热热!三伏天到了应该注意什么?一起看看❗
+
+                第二:生成过程有如下的规范、约束和建议:
+                1.标题开头包含醒目emoji🔴,整体字符长度控制在10-20;
+                2.不能包含#话题和@人;
+                3.不能编造:不能加入原标题没有的实体信息,如原标题没有养老金,不能在生成的标题中出现养老金;
+                4.不能使用无实质信息和强烈诱导点击、紧急、夸张、震惊的描述:在提高标题吸引力的同时,严格落实不使用“必看”、“错过悔恨终生”类描述,错误危险标题示例:
+                万万想不到真的太好了看了3遍,你也快看看吧!
+                🌸绝对不能错过,快打开看看,越快越好
+                所有老年人一定要看
+                天大的好消息,5月开始实施❗
+                就在刚刚,中国突然传出重磅消息,所有人都不敢相信!🚩
+                丧尽天良!为什么生病的人越来越多,原来吃的是这些🎈
+                今年的端午节太特殊,一辈子难遇一次!一定要看!错过别后悔
+                好消息来了,千万别划走!
+                紧急!已爆发,错过就晚了😱
+
+                输出格式:要求输出格式为符合RFC8259标准的JSON格式的字符串,不要以代码块形式返回,返回一个string类型的新标题。
+                '''
+
+        url = "http://aigc.piaoquantv.com/aigc-server/aigc/conversation"
+        headers = {
+            "Content-Type": "application/json"
+        }
+        payload = {
+            "auth": "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",
+            "openAiGptParam": {
+                "model": "gpt-4o",
+                "temperature": 0.5,
+                "messages": [
+                    {
+                        "role": "system",
+                        "content": content
+                    },
+                    {
+                        "role": "user",
+                        "content": old_title
+                    }
+                ]
+            }
+        }
+        try:
+            time.sleep(2)
+            response = requests.post(url, headers=headers, json=payload)
+            response = response.json()
+            content = response['data']['choices'][0]['message']['content']
+            data = json.loads(content)
+            title = data["title"]
+            return title
+        except Exception:
+            return "🔴好漂亮的视频,给你最美的祝福❗"

+ 0 - 0
common/kimi_help.py


+ 28 - 1
common/sql_help.py

@@ -1,6 +1,6 @@
 import os
 import sys
-from datetime import datetime, timedelta
+from typing import Optional
 
 
 
@@ -65,3 +65,30 @@ class sqlCollect():
         MysqlHelper.update_values(
             sql=insert_sql
         )
+
+    """
+    判断该任务id是否用过
+    """
+    @classmethod
+    def is_used(cls, photo_id):
+        sql = """
+                SELECT photo_id
+                FROM ks_category_video
+                WHERE photo_id = %s  
+            """
+        data = MysqlHelper.get_values(sql, (str(photo_id)))
+        if len(data) == 0 or data == ():
+            return False
+        return True
+
+    @classmethod
+    def insert_ks_data(cls, user_name: str, user_sex: str, time_data, caption: str, view_count: str, like_count: str,
+                       share_count: str, duration: str, main_mv_url: str, thumbnail_url: str, user_id: str, status: str,
+                       photo_id: str, category_name: str, age: str, oss_object: Optional[str] = None,
+                       video_uid: Optional[str] = None):
+        current_time = datetime.now()
+        formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
+        insert_sql = f"""INSERT INTO ks_category_video (user_name, user_sex, time_data, caption, view_count, like_count, share_count, duration, main_mv_url, thumbnail_url, user_id, status, age_proportion, video_oss_path, pq_video_id, update_time, photo_id, category_name) values ("{user_name}", "{user_sex}", "{time_data}", "{caption}", "{view_count}", "{like_count}", "{share_count}", "{duration}", "{main_mv_url}", "{thumbnail_url}", "{user_id}", "{status}", "{age}", "{oss_object}", "{video_uid}", "{formatted_time}", "{photo_id}", "{category_name}")"""
+        res = MysqlHelper.update_values(
+            sql=insert_sql
+        )

+ 97 - 0
common/tts_help.py

@@ -0,0 +1,97 @@
+# -*- coding: UTF-8 -*-
+# Python 2.x引入httplib模块。
+# import httplib
+# Python 3.x引入http.client模块。
+import http.client
+# Python 2.x引入urllib模块。
+# import urllib
+# Python 3.x引入urllib.parse模块。
+import urllib.parse
+import json
+def processGETRequest(appKey, token, text, audioSaveFile, format, sampleRate) :
+    host = 'nls-gateway-cn-shanghai.aliyuncs.com'
+    url = 'https://' + host + '/stream/v1/tts'
+    # 设置URL请求参数
+    url = url + '?appkey=' + appKey
+    url = url + '&token=' + token
+    url = url + '&text=' + text
+    url = url + '&format=' + format
+    url = url + '&sample_rate=' + str(sampleRate)
+    # voice 发音人,可选,默认是xiaoyun。
+    # url = url + '&voice=' + 'xiaoyun'
+    # volume 音量,范围是0~100,可选,默认50。
+    # url = url + '&volume=' + str(50)
+    # speech_rate 语速,范围是-500~500,可选,默认是0。
+    # url = url + '&speech_rate=' + str(0)
+    # pitch_rate 语调,范围是-500~500,可选,默认是0。
+    # url = url + '&pitch_rate=' + str(0)
+    print(url)
+    # Python 2.x请使用httplib。
+    # conn = httplib.HTTPSConnection(host)
+    # Python 3.x请使用http.client。
+    conn = http.client.HTTPSConnection(host)
+    conn.request(method='GET', url=url)
+    # 处理服务端返回的响应。
+    response = conn.getresponse()
+    print('Response status and response reason:')
+    print(response.status ,response.reason)
+    contentType = response.getheader('Content-Type')
+    print(contentType)
+    body = response.read()
+    if 'audio/mpeg' == contentType :
+        with open(audioSaveFile, mode='wb') as f:
+            f.write(body)
+        print('The GET request succeed!')
+    else :
+        print('The GET request failed: ' + str(body))
+    conn.close()
+def processPOSTRequest(appKey, token, text, audioSaveFile, format, sampleRate) :
+    host = 'nls-gateway-cn-shanghai.aliyuncs.com'
+    url = 'https://' + host + '/stream/v1/tts'
+    # 设置HTTPS Headers。
+    httpHeaders = {
+        'Content-Type': 'application/json'
+        }
+    # 设置HTTPS Body。
+    body = {'appkey': appKey, 'token': token, 'text': text, 'format': format, 'sample_rate': sampleRate}
+    body = json.dumps(body)
+    print('The POST request body content: ' + body)
+    # Python 2.x请使用httplib。
+    # conn = httplib.HTTPSConnection(host)
+    # Python 3.x请使用http.client。
+    conn = http.client.HTTPSConnection(host)
+    conn.request(method='POST', url=url, body=body, headers=httpHeaders)
+    # 处理服务端返回的响应。
+    response = conn.getresponse()
+    print('Response status and response reason:')
+    print(response.status ,response.reason)
+    contentType = response.getheader('Content-Type')
+    print(contentType)
+    body = response.read()
+    if 'audio/mpeg' == contentType :
+        with open(audioSaveFile, mode='wb') as f:
+            f.write(body)
+        print('The POST request succeed!')
+    else :
+        print('The POST request failed: ' + str(body))
+    conn.close()
+appKey = 'KZChElSawT5Zue3n'
+token = 'fbb04d8f368e4394ac7172a1225c0720'
+text = '今天是周五,天气挺好的。'
+# 采用RFC 3986规范进行urlencode编码。
+textUrlencode = text
+# Python 2.x请使用urllib.quote。
+# textUrlencode = urllib.quote(textUrlencode, '')
+# Python 3.x请使用urllib.parse.quote_plus。
+textUrlencode = urllib.parse.quote_plus(textUrlencode)
+textUrlencode = textUrlencode.replace("+", "%20")
+textUrlencode = textUrlencode.replace("*", "%2A")
+textUrlencode = textUrlencode.replace("%7E", "~")
+print('text: ' + textUrlencode)
+audioSaveFile = '/Users/tzld/Desktop/video_rewriting/common/syAudio.MP3'
+format = 'MP3'
+sampleRate = 16000
+# GET请求方式
+processGETRequest(appKey, token, textUrlencode, audioSaveFile, format, sampleRate)
+# POST请求方式
+# processPOSTRequest(appKey, token, text, audioSaveFile, format, sampleRate)

+ 302 - 0
data_channel/kuaishouchuangzuozhe.py

@@ -0,0 +1,302 @@
+import json
+import os
+from hashlib import md5
+import requests
+import time
+from urllib.parse import urlencode
+from datetime import datetime, timedelta
+
+from common import Oss, Feishu, Common
+from common.sql_help import sqlCollect
+
+headers = {
+    'Accept-Language': 'zh-cn',
+    'Connection': 'keep-alive',
+    'Content-Type': 'application/x-www-form-urlencoded',
+    'Host': 'creator-app.kuaishou.com',
+    'User-Agent': 'kwai-android aegon/3.12.1',
+}
+class KsFeedVideo:
+    CATEGORY_IDS = {
+        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: "人文"
+    }
+    current_category_index = 0
+
+    @staticmethod
+    def calculate_sig(data):
+        src = ''.join([f'{key}={data[key]}' for key in sorted(data.keys())])
+        salt = '08d8eece8e83'
+        return md5(f'{src}{salt}'.encode()).hexdigest()
+
+
+    """
+    切换品类
+    """
+    @classmethod
+    def switch_category(cls):
+        if cls.current_category_index >= len(cls.CATEGORY_IDS):
+            cls.current_category_index = 0
+        category_id = list(cls.CATEGORY_IDS.keys())[cls.current_category_index]
+        url = 'https://creator-app.kuaishou.com/rest/bamboo/inspiration/n/category/confirm/optimize'
+        data = {
+            'isRecommendChange': False,
+            'categoryId': category_id,
+            # 'kuaishou.api_st': "Cg9rdWFpc2hvdS5hcGkuc3QSkAGMQoIK2ZpwlQszYISTxSFxzugi58w2U5gpPqa6an0eU6MFcVsXq2rd_K16UTItZ_OzPV-4jmVN5rNXKXW9jL97JV79Y9PqxaR9xOIr1TEyDzpOq2GM-0W1QRW3M8Li_J6NZ5t1hRFCWHBlOESjiBWs7vq4m1bq_ml0dZ6pgEDfpsWNpBaLRzwZwOO1mD4LqO4aEokh6uHql0RmmtbfoBF25r7QOyIgqNv0TBf6mlwS3bjE0K6sl08M1mMPjW1PB9e0Qr494H8oBTAB",
+            'kuaishou.api_st': 'Cg9rdWFpc2hvdS5hcGkuc3QSkAE_VoKJQaM0WajPO6D5L7oDL1T27Alg2mU-kCyJ3UYVcMHrcHWvW25h0I8N99ji9ZU5hLqzw8zaJ9X2U7RbOnoCL6cHJYqdq8UDVpz7sXWOmaNPM5iCYJ7zLa4aXgSAzpHoGhzOqVSr1o3Y7BSJ57WMhJGECPyATpfd6MPBmftxqYXyR_BEvC8x3O_4mboHODAaEgGwS-thQkgSvdABsv26PXMiGyIgTpI18EY0ssCCp3tPqI1swbohPO3jH36-5NV0yKMdJWQoBTAB',
+            'client_key': '214c9979',
+        }
+        sig = cls.calculate_sig(data)
+        data['sig'] = sig
+        response = requests.post(url=url, headers=headers, data=data)
+        body = response.content.decode()
+        cls.current_category_index += 1
+        return body
+
+    """
+    获取feed流信息
+    """
+    @classmethod
+    def get_feed_list(cls):
+        cls.switch_category()
+        url = 'https://creator-app.kuaishou.com/rest/bamboo/inspiration/n/feed'
+        data = {
+            'cs': False,
+            'kuaishou.api_st': 'Cg9rdWFpc2hvdS5hcGkuc3QSkAE_VoKJQaM0WajPO6D5L7oDL1T27Alg2mU-kCyJ3UYVcMHrcHWvW25h0I8N99ji9ZU5hLqzw8zaJ9X2U7RbOnoCL6cHJYqdq8UDVpz7sXWOmaNPM5iCYJ7zLa4aXgSAzpHoGhzOqVSr1o3Y7BSJ57WMhJGECPyATpfd6MPBmftxqYXyR_BEvC8x3O_4mboHODAaEgGwS-thQkgSvdABsv26PXMiGyIgTpI18EY0ssCCp3tPqI1swbohPO3jH36-5NV0yKMdJWQoBTAB',
+            # 'kuaishou.api_st': "Cg9rdWFpc2hvdS5hcGkuc3QSkAGMQoIK2ZpwlQszYISTxSFxzugi58w2U5gpPqa6an0eU6MFcVsXq2rd_K16UTItZ_OzPV-4jmVN5rNXKXW9jL97JV79Y9PqxaR9xOIr1TEyDzpOq2GM-0W1QRW3M8Li_J6NZ5t1hRFCWHBlOESjiBWs7vq4m1bq_ml0dZ6pgEDfpsWNpBaLRzwZwOO1mD4LqO4aEokh6uHql0RmmtbfoBF25r7QOyIgqNv0TBf6mlwS3bjE0K6sl08M1mMPjW1PB9e0Qr494H8oBTAB",
+            'client_key': '214c9979',
+        }
+        sig = cls.calculate_sig(data)
+        data['sig'] = sig
+        response = requests.post(url=url, headers=headers, data=data)
+        body = response.content.decode()
+        return body
+
+    """
+    获取观众画像
+    """
+    @classmethod
+    def analyze_photo(cls, photo_id):
+        url = 'https://creator-app.kuaishou.com/rest/bamboo/inspiration/n/photo/analysis'
+
+        headers = {
+            'Accept-Language': 'zh-cn',
+            'Connection': 'keep-alive',
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'Host': 'creator-app.kuaishou.com',
+        }
+        data = {
+            'photoId': photo_id,
+            'client_key': '214c9979',
+        }
+        sig = cls.calculate_sig(data)
+        data['sig'] = sig
+        response = requests.post(url=url, headers=headers, data=data)
+        body = response.content.decode()
+        json_body = json.loads(body)
+        user_range = json_body['data']['play']['userRange']
+        if len(user_range) == 0:
+            return False, "无画像"
+        age_range = user_range['ageRange']
+        value = age_range[5]['value']
+        value = int(value.strip('%'))
+        if value >= 50:
+            return False, value
+        else:
+            return True, value
+
+    """
+    视频时长转换成秒
+    """
+    @classmethod
+    def milliseconds_to_seconds(cls, milliseconds):
+        seconds = milliseconds / 1000
+        return int(seconds)
+
+    """
+    判断当前视频是否在90天内
+    """
+    @classmethod
+    def get_video_data(cls, timestamp_str):
+        timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S")
+        # 获取当前时间
+        current_time = datetime.now()
+        difference = current_time - timestamp
+        if difference <= timedelta(days=90):
+            return False
+        else:
+            return True
+    """
+    获取票圈ID
+    """
+    @classmethod
+    def get_id_by_category(cls, category_name):
+        category_list = [
+            {"id": 71502003, "category": "生活"},
+            {"id": 71502004, "category": "才艺"},
+            {"id": 71502005, "category": "时尚"},
+            {"id": 71502006, "category": "宠物"},
+            {"id": 71502007, "category": "读书"},
+            {"id": 71502008, "category": "二次元"},
+            {"id": 71502009, "category": "家居"},
+            {"id": 71502010, "category": "数码"},
+            {"id": 71502011, "category": "搞笑"},
+            {"id": 71502012, "category": "健康"},
+            {"id": 71502013, "category": "旅游"},
+            {"id": 71502014, "category": "美食"},
+            {"id": 71502015, "category": "美妆"},
+            {"id": 71502016, "category": "汽车"},
+            {"id": 71502018, "category": "亲子"},
+            {"id": 71502019, "category": "情感"},
+            {"id": 71502020, "category": "三农"},
+            {"id": 71502021, "category": "摄影"},
+            {"id": 71502022, "category": "舞蹈"},
+            {"id": 71502023, "category": "颜值"},
+            {"id": 71502024, "category": "音乐"},
+            {"id": 71502025, "category": "影视"},
+            {"id": 71502026, "category": "短剧"},
+            {"id": 71502027, "category": "游戏"},
+            {"id": 71502028, "category": "运动"},
+            {"id": 71502029, "category": "资讯"},
+            {"id": 71502030, "category": "人文"}
+        ]
+        for category in category_list:
+            if category['category'] == category_name:
+                return category['id']
+        return None
+
+    """
+    新生成视频上传到对应账号下
+    """
+    @classmethod
+    def insert_piaoquantv(cls, new_video_path, new_title, n_id, cover):
+
+        url = "https://vlogapi.piaoquantv.com/longvideoapi/crawler/video/send"
+        headers = {
+            'User-Agent': 'PQSpeed/486 CFNetwork/1410.1 Darwin/22.6.0',
+            'cookie': 'JSESSIONID=4DEA2B5173BB9A9E82DB772C0ACDBC9F; JSESSIONID=D02C334150025222A0B824A98B539B78',
+            'referer': 'http://appspeed.piaoquantv.com',
+            'token': '524a8bc871dbb0f4d4717895083172ab37c02d2f',
+            'accept-language': 'zh-CN,zh-Hans;q=0.9',
+            'Content-Type': 'application/x-www-form-urlencoded'
+        }
+        payload = {
+            'coverImgPath': cover,
+            'deviceToken': '9ef064f2f7869b3fd67d6141f8a899175dddc91240971172f1f2a662ef891408',
+            'fileExtensions': 'MP4',
+            'loginUid': n_id,
+            'networkType': 'Wi-Fi',
+            'platform': 'iOS',
+            'requestId': 'fb972cbd4f390afcfd3da1869cd7d001',
+            'sessionId': '362290597725ce1fa870d7be4f46dcc2',
+            'subSessionId': '362290597725ce1fa870d7be4f46dcc2',
+            'title': new_title,
+            'token': '524a8bc871dbb0f4d4717895083172ab37c02d2f',
+            'uid': n_id,
+            'versionCode': '486',
+            'versionName': '3.4.12',
+            'videoFromScene': '1',
+            'videoPath': new_video_path,
+            'viewStatus': '1'
+        }
+        encoded_payload = urlencode(payload)
+        response = requests.request("POST", url, headers=headers, data=encoded_payload)
+        data = response.json()
+        code = data["code"]
+        if code == 0:
+            new_video_id = data["data"]["id"]
+            return new_video_id
+        else:
+            return None
+
+    @classmethod
+    def get_data(cls, number):
+        list = []
+        for category_id, category_name in cls.CATEGORY_IDS.items():
+            try:
+                feed_data = cls.get_feed_list()
+                feed_data = json.loads(feed_data)
+                feeds = feed_data['feeds']
+                for feed in feeds:
+                    photo_id = feed["photo_id"]  # 视频ID
+                    status = sqlCollect.is_used(photo_id)
+                    if status:
+                        continue
+                    user_name = feed["user_name"]  # 用户名
+                    user_sex = feed["user_sex"]  # 性别 F为女,U为男
+                    time_data = feed["time"]  # 发布时间
+                    caption = feed["caption"]  # 标题
+                    view_count = feed["view_count"]  # 浏览数
+                    like_count = feed["like_count"]  # 点赞数
+                    share_count = feed["share_count"]  # 分享数
+                    duration = feed["duration"]  # 时长/秒
+                    duration = cls.milliseconds_to_seconds(duration)
+                    main_mv_url = feed["main_mv_url"]  # 视频链接
+                    thumbnail_url = feed["thumbnail_url"]  # 视频封面
+                    user_id = feed["user_id"]  # 用户id非用户主页id
+                    value, age = cls.analyze_photo(photo_id)
+                    if value:
+                        sqlCollect.insert_ks_data(user_name, user_sex, time_data, caption, view_count, like_count,
+                                                  share_count, duration, main_mv_url, thumbnail_url, user_id, '1',
+                                                  photo_id, category_name, age, oss_object=None, video_uid=None)
+
+                        continue
+                    video_percent = '%.4f' % (share_count / view_count)
+                    special = float(0.001)
+                    if float(video_percent) < special or share_count < 500 or duration < 30 or duration > 600:
+                        sqlCollect.insert_ks_data(user_name, user_sex, time_data, caption, view_count, like_count, share_count, duration, main_mv_url, thumbnail_url, user_id, '1', photo_id, category_name, age, oss_object=None, video_uid=None)
+                        continue
+
+                    sqlCollect.insert_ks_data(user_name, user_sex, time_data, caption, view_count,
+                                              like_count, share_count, duration, main_mv_url, thumbnail_url,
+                                              user_id, '0', photo_id, category_name, age, oss_object=None, video_uid=None)
+                    all_data = {"video_id": photo_id, "cover": thumbnail_url, "video_url": main_mv_url, "rule": video_percent,
+                                "old_title": caption}
+                    list.append(all_data)
+                    current_time = datetime.now()
+                    formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
+                    values = [
+                        [category_name, user_name, photo_id, user_sex, caption, view_count, like_count, share_count, duration,
+                         main_mv_url, thumbnail_url, user_id, age, '', '', time_data, formatted_time]]
+                    Feishu.insert_columns("PlcisKhObhzmBothRutc65sJnph", "8fQxFv", "ROWS", 2, 3)
+                    time.sleep(0.5)
+                    Feishu.update_values("PlcisKhObhzmBothRutc65sJnph", "8fQxFv", "A2:Z2", values)
+                    if len(list) == int(number):
+                        Common.logger("log").info(f"获取快手创作者视频总数:{len(list)}\n")
+                        return list
+                time.sleep(5)
+            except Exception as exc:
+                print(f"异常信息: {exc}")
+                continue
+        return list
+
+
+
+# Example usage:
+if __name__ == "__main__":
+    KsFeedVideo.get_data()

+ 72 - 0
job_ksczz.py

@@ -0,0 +1,72 @@
+import os
+import concurrent.futures
+import re
+
+import schedule
+import time
+import threading
+from common import Material, Common, Feishu
+# 控制读写速度的参数
+from video_rewriting.video_prep import getVideo
+
+MAX_BPS = 120 * 1024 * 1024  # 120MB/s
+MAX_WORKERS = os.cpu_count() * 2  # 线程池最大工作线程数量
+READ_WRITE_CHUNK_SIZE = 1024 * 1024  # 每次读写的块大小 (1MB)
+SLEEP_INTERVAL = READ_WRITE_CHUNK_SIZE / MAX_BPS  # 控制每次读写的延迟时间
+# 全局锁,用于同步读写操作
+lock = threading.Lock()
+
+
+def video_task_start(data):
+    mark = getVideo.video_task(data)
+    print(f"返回用户名{mark}")
+
+
+# data = Material.feishu_list()
+# video_task_start(data[9])
+
+
+def controlled_io_operation(data):
+    with lock:
+        start_time = time.time()
+        time.sleep(SLEEP_INTERVAL)
+        end_time = time.time()
+        elapsed_time = end_time - start_time
+        if elapsed_time < SLEEP_INTERVAL:
+            time.sleep(SLEEP_INTERVAL - elapsed_time)
+    video_task_start(data)
+
+
+
+
+def video_start():
+    print("开始执行生成视频脚本.")
+
+    data = Material.feishu_list()
+    data = data[9]
+    with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
+        futures = {executor.submit(controlled_io_operation, data)}
+        for future in concurrent.futures.as_completed(futures):
+            try:
+                future.result()
+                print("处理结果: 成功")
+            except concurrent.futures.TimeoutError:
+                print("任务超时,已取消.")
+            except Exception as e:
+                print("处理任务时出现异常:", e)
+    print("执行生成视频脚本结束.")
+
+video_start()
+
+
+# schedule.every(6).hours.do(video_start)
+schedule.every(20).minutes.do(video_start)
+
+
+
+
+while True:
+    schedule.run_pending()
+    time.sleep(1)
+
+

+ 37 - 6
video_rewriting/video_prep.py

@@ -8,8 +8,10 @@ from datetime import datetime
 import concurrent.futures
 from common import Material, Feishu, Common, Oss
 from common.ffmpeg import FFmpeg
+from common.gpt4o_help import GPT4o
 from data_channel.douyin import DY
 from data_channel.kuaishou import KS
+from data_channel.kuaishouchuangzuozhe import KsFeedVideo
 from data_channel.piaoquan import PQ
 from common.sql_help import sqlCollect
 from data_channel.shipinhao import SPH
@@ -98,10 +100,6 @@ class getVideo:
                 channel_url = [channel_urls]
             for url in channel_url:
                 Common.logger("log").info(f"{task_mark}下的用户:{channel_url}开始获取视频")
-                if '/' in title:
-                    titles = title.split('/')
-                else:
-                    titles = [title]
                 if channel_id == "抖音":
                     data_list = DY.get_dy_url(task_mark, url, number, mark, feishu_id, cookie_sheet, channel_id, name)
                 elif channel_id == "票圈":
@@ -110,6 +108,13 @@ class getVideo:
                     data_list = SPH.get_sph_url(task_mark, url, number, mark)
                 elif channel_id == "快手":
                     data_list = KS.get_ks_url(task_mark, url, number, mark, feishu_id, cookie_sheet, channel_id, name)
+                elif channel_id == "快手创作者版":
+                    data_list = KsFeedVideo.get_data(number)
+                    if len(data_list) == 0:
+                        Common.logger("log").info(f"{task_mark}下的视频ID{url} 已经改造过了")
+                        Feishu.bot("快手创作者版", '机器自动改造消息通知', f'本轮没有获取到改造的视频链接', "王雪珂")
+                        cls.remove_files(video_path_url)
+                        continue
                 if len(data_list) == 0:
                     Common.logger("log").info(f"{task_mark}下的视频ID{url} 已经改造过了")
                     Feishu.bot(mark, '机器自动改造消息通知', f'{task_mark}任务下的用户ID{url},没有已经改造的视频了', name)
@@ -119,6 +124,27 @@ class getVideo:
 
                 try:
                     for video in data_list:
+                        new_title = video['old_title'].strip().replace("\n", "") \
+                            .replace("/", "").replace("\\", "").replace("\r", "") \
+                            .replace(":", "").replace("*", "").replace("?", "") \
+                            .replace("?", "").replace('"', "").replace("<", "") \
+                            .replace(">", "").replace("|", "").replace(" ", "") \
+                            .replace("&NBSP", "").replace(".", "。").replace(" ", "") \
+                            .replace("'", "").replace("#", "").replace("Merge", "")
+                        if title == "原标题":
+                            if new_title == "" or len(new_title) == 0 or new_title == None:
+                                new_title = '🔴好漂亮的视频,给你最美的祝福❗'
+                        elif title == "AI标题":
+                            if new_title == "" or len(new_title) == 0 or new_title == None:
+                                new_title = '🔴好漂亮的视频,给你最美的祝福❗'
+                            else:
+                                new_title = GPT4o.get_ai_title(new_title)
+                        else:
+                            if '/' in title:
+                                titles = title.split('/')
+                            else:
+                                titles = [title]
+                            new_title = random.choice(titles)
                         v_id = video["video_id"]
                         cover = video["cover"]
                         video_url = video["video_url"]
@@ -197,7 +223,7 @@ class getVideo:
                         if status == 200:
                             oss_object_key = oss_object_key.get("oss_object_key")
                             time.sleep(1)
-                            new_title = random.choice(titles)
+
                             code = PQ.insert_piaoquantv(oss_object_key, new_title, cover, piaoquan_id)
                             if code:
                                 Common.logger("log").info(f"{task_mark}下的视频ID{v_id}发送成功")
@@ -205,7 +231,10 @@ class getVideo:
                                 current_time = datetime.now()
                                 formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
                                 sqlCollect.insert_machine_making_data(name, task_mark, channel_id, url, v_id, piaoquan_id, new_title, code, formatted_time, old_title)
-                                values = [[name, task_mark, channel_id, url, v_id, piaoquan_id, old_title, new_title, str(code), formatted_time, str(rule)]]
+                                if title == "原标题" or title == "AI标题":
+                                    values = [[name, task_mark, channel_id, url, v_id, piaoquan_id, old_title, title,new_title, str(code), formatted_time, str(rule)]]
+                                else:
+                                    values = [[name, task_mark, channel_id, url, v_id, piaoquan_id, old_title, "",new_title, str(code), formatted_time, str(rule)]]
                                 # 使用锁保护表格插入操作
                                 with lock:
                                     if name == "王雪珂":
@@ -226,6 +255,8 @@ class getVideo:
                                         sheet = "fBdxIQ"
                                     elif name == "信欣":
                                         sheet = "lPe1eT"
+                                    elif name == "快手创作者版品类推荐流":
+                                        sheet = "1aOVQa"
                                     Feishu.insert_columns("ILb4sa0LahddRktnRipcu2vQnLb", sheet, "ROWS", 1, 2)
                                     time.sleep(0.5)
                                     Feishu.update_values("ILb4sa0LahddRktnRipcu2vQnLb", sheet, "A2:Z2", values)