zhangyong 6 月之前
父節點
當前提交
83a2b34d9d
共有 5 個文件被更改,包括 306 次插入41 次删除
  1. 82 24
      carry_video/carry_video.py
  2. 24 1
      common/download_video.py
  3. 3 0
      common/feishu_form.py
  4. 161 16
      common/ffmpeg.py
  5. 36 0
      data_channel/piaoquan.py

+ 82 - 24
carry_video/carry_video.py

@@ -382,12 +382,8 @@ class CarryViode:
                     video_path = FFmpeg.video_ggduration(video_path, file_path, data["video_clipping_time"])
 
                 if data['trailer_share']:
-                    if data['trailer_share'] ==  "AI片尾引导" or data['trailer_share'] ==  "AI片尾引导1" :
-                        prompt = Material.get_propmt_data(data['trailer_share'])
-
-                        pw_srt_text = GPT4oMini.get_ai_mini_pw(title, prompt)
-                    else:
-                        pw_srt_text = str(data['trailer_share'])
+                    prompt = Material.get_propmt_data(data['trailer_share'])
+                    pw_srt_text = GPT4oMini.get_ai_mini_pw(title, prompt)
                     voice = data['trailer_share_audio']
                     if voice:
                         if ',' in voice:
@@ -447,29 +443,90 @@ class CarryViode:
                                           "【 搬运&改造效率工具失败通知 】")
                         return
                     logger.info(f"[+] {REDIS_NAME}的{data}数据片尾音频下载成功")
-                    jpg_path = FFmpeg.video_png(video_path, file_path)  # 生成视频最后一帧jpg
-                    if not os.path.exists(jpg_path) or os.path.getsize(jpg_path) == 0:
-                        data["transform_rule"] = "仅改造"
-                        in_carry_video_data(REDIS_NAME, json.dumps(data, ensure_ascii=False, indent=4))
-                        logger.error(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧失败")
-                        AliyunLogger.logging(data["name"], "效率工具",tag_transport_channel, data["video_url"],
-                                             "改造失败,获取最后一帧失败", "3001", str(data))
-                        text = (
-                            f"**负责人**: {data['name']}\n"
-                            f"**内容**: {data}\n"
-                            f"**失败信息**: 获取视频最后一帧失败\n"
-                        )
-                        Feishu.finish_bot(text,
-                                          "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
-                                          "【 搬运&改造效率工具失败通知 】")
-                        return
-                    logger.info(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧成功")
+                    if "AI片尾引导" not in data['trailer_share']:
+                        jpg_path = FFmpeg.video_png(video_path, file_path)  # 生成视频最后一帧jpg
+                        if not os.path.exists(jpg_path) or os.path.getsize(jpg_path) == 0:
+                            data["transform_rule"] = "仅改造"
+                            in_carry_video_data(REDIS_NAME, json.dumps(data, ensure_ascii=False, indent=4))
+                            logger.error(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧失败")
+                            AliyunLogger.logging(data["name"], "效率工具",tag_transport_channel, data["video_url"],
+                                                 "改造失败,获取最后一帧失败", "3001", str(data))
+                            text = (
+                                f"**负责人**: {data['name']}\n"
+                                f"**内容**: {data}\n"
+                                f"**失败信息**: 获取视频最后一帧失败\n"
+                            )
+                            Feishu.finish_bot(text,
+                                              "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
+                                              "【 搬运&改造效率工具失败通知 】")
+                            return
+                        logger.info(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧成功")
+
+                    else:
+                        rg_pw = str(data["trailer_share"])
+                        if ',' in rg_pw:
+                            rg_pw_list = rg_pw.split(',')
+                        else:
+                            rg_pw_list = [rg_pw]
+                        rg_pw_url_list = PQ.get_pq_oss(rg_pw_list)
+                        if not rg_pw_url_list:
+                            AliyunLogger.logging(data["name"], "效率工具", tag_transport_channel, data["video_url"],
+                                                 "无法获取站内视频链接", "3001", str(data))
+                            text = (
+                                f"**负责人**: {data['name']}\n"
+                                f"**内容**: {data}\n"
+                                f"**失败信息**: 无法获取站内视频链接\n"
+                            )
+                            Feishu.finish_bot(text,
+                                              "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
+                                              "【 搬运&改造效率工具失败通知 】")
+                            return
+                        pw_url_duration = FFmpeg.get_http_duration([pw_url])
+                        pw_videos_duration = FFmpeg.get_http_duration(rg_pw_url_list)
+                        if pw_videos_duration < pw_url_duration:
+                            jpg_path = FFmpeg.video_png(video_path, file_path)  # 生成视频最后一帧jpg
+                            if not os.path.exists(jpg_path) or os.path.getsize(jpg_path) == 0:
+                                data["transform_rule"] = "仅改造"
+                                in_carry_video_data(REDIS_NAME, json.dumps(data, ensure_ascii=False, indent=4))
+                                logger.error(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧失败")
+                                AliyunLogger.logging(data["name"], "效率工具", tag_transport_channel, data["video_url"],
+                                                     "改造失败,获取最后一帧失败", "3001", str(data))
+                                text = (
+                                    f"**负责人**: {data['name']}\n"
+                                    f"**内容**: {data}\n"
+                                    f"**失败信息**: 获取视频最后一帧失败\n"
+                                )
+                                Feishu.finish_bot(text,
+                                                  "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
+                                                  "【 搬运&改造效率工具失败通知 】")
+                                return
+                            logger.info(f"[+] {REDIS_NAME}的{data}数据片尾获取最后一帧成功")
+                        else:
+                            rg_pw_url =DownLoad.download_pq_video(file_path, rg_pw_url_list)
+                            rg_pw_list = FFmpeg.concatenate_videos(rg_pw_url, file_path)
+                            if not os.path.exists(rg_pw_list) or os.path.getsize(rg_pw_list) == 0:
+                                data["transform_rule"] = "仅改造"
+                                in_carry_video_data(REDIS_NAME, json.dumps(data, ensure_ascii=False, indent=4))
+                                logger.error(f"[+] {REDIS_NAME}的{data}数据片尾拼接失败")
+                                AliyunLogger.logging(data["name"], "效率工具", tag_transport_channel, data["video_url"],
+                                                     "改造失败,片尾拼接失败", "3001", str(data))
+                                text = (
+                                    f"**负责人**: {data['name']}\n"
+                                    f"**内容**: {data}\n"
+                                    f"**失败信息**: 片尾拼接失败\n"
+                                )
+                                Feishu.finish_bot(text,
+                                                  "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
+                                                  "【 搬运&改造效率工具失败通知 】")
+                                return
+                            jpg_path = FFmpeg.video_640(rg_pw_list, file_path+"rg_")
+                            logger.info(f"[+] {REDIS_NAME}的{data}生成人工片尾成功")
                     pw_path = FFmpeg.pw_video(jpg_path, file_path, pw_mp3_path, pw_srt)  # 生成片尾视频
                     if not os.path.exists(pw_path) or os.path.getsize(pw_path) == 0:
                         data["transform_rule"] = "仅改造"
                         in_carry_video_data(REDIS_NAME, json.dumps(data, ensure_ascii=False, indent=4))
                         logger.error(f"[+] {REDIS_NAME}的{data}数据片尾拼接失败")
-                        AliyunLogger.logging(data["name"], "效率工具",tag_transport_channel, data["video_url"],
+                        AliyunLogger.logging(data["name"], "效率工具", tag_transport_channel, data["video_url"],
                                              "改造失败,片尾拼接失败", "3001", str(data))
                         text = (
                             f"**负责人**: {data['name']}\n"
@@ -480,6 +537,7 @@ class CarryViode:
                                           "https://open.feishu.cn/open-apis/bot/v2/hook/65bc5463-dee9-46d0-bc2d-ec6c49a8f3cd",
                                           "【 搬运&改造效率工具失败通知 】")
                         return
+
                     logger.info(f"[+] {REDIS_NAME}的{data}数据合并开始拼接")
                     video_path = FFmpeg.h_b_video(video_path, pw_path, file_path)
                     video_path = FFmpeg.single_video(video_path, file_path, data["video_share"])

+ 24 - 1
common/download_video.py

@@ -1,4 +1,6 @@
 import os
+import time
+import uuid
 from urllib.parse import urlparse
 
 import requests
@@ -71,4 +73,25 @@ class DownLoad:
 
     @classmethod
     def convert_ts_to_mp4(cls, ts_file_path, mp4_file_path):
-        os.system(f'ffmpeg -i {ts_file_path} -c copy {mp4_file_path}')
+        os.system(f'ffmpeg -i {ts_file_path} -c copy {mp4_file_path}')
+
+    @classmethod
+    def download_pq_video(cls,video_path_url , video_url_list):
+        video_list = []
+        for video_url in video_url_list:
+            video = f'{video_path_url}{str(uuid.uuid4())}.mp4'
+            try:
+                payload = {}
+                headers = {}
+                response = requests.request("GET", video_url, headers=headers, data=payload, timeout=60)
+                if response.status_code == 200:
+                    # 以二进制写入模式打开文件
+
+                    with open(f"{video}", "wb") as file:
+                        # 将响应内容写入文件
+                        file.write(response.content)
+                    video_list.append(video)
+                time.sleep(1)
+            except Exception:
+                continue
+        return video_list

+ 3 - 0
common/feishu_form.py

@@ -66,11 +66,14 @@ class Material():
     @classmethod
     def get_propmt_data(cls, trailer_share):
         try:
+            if "AI片尾引导" not in trailer_share:
+                trailer_share = "AI片尾引导"
             data = Feishu.get_values_batch( "Wj0TsRKc0hZrHQtmtg4cZZIwn0c", "Yxg7EK" )
             for row in data[1:]:
                 name = row[0]
                 if trailer_share == name:
                     return row[1]
+            return
         except:
             return None
 

+ 161 - 16
common/ffmpeg.py

@@ -1,10 +1,12 @@
 import asyncio
+import json
 import os
 import subprocess
 import time
 from typing import List
 
 import cv2
+import requests
 from loguru import logger
 from mutagen.mp3 import MP3
 
@@ -172,6 +174,21 @@ class FFmpeg():
         except Exception as e:
             return video_url
 
+    @classmethod
+    def concatenate_videos(cls, videos_paths, file_path):
+        video_url = file_path + 'rg_pw.mp4'
+        list_filename = file_path + 'rg_pw.txt'
+        with open(list_filename, "w") as f:
+            for video_path in videos_paths:
+                f.write(f"file '{video_path}'\n")
+        try:
+            cls.asyncio_run_subprocess(
+                ["ffmpeg", "-f", "concat", "-safe", "0", "-i", list_filename, "-c", "copy", video_url], timeout=420)
+            logger.info(f"[+] 视频转为640像素成功")
+            return video_url
+        except Exception as e:
+            return video_url
+
     """视频拼接到一起"""
     @classmethod
     def h_b_video(cls, video_path, pw_path, file_path):
@@ -256,21 +273,43 @@ class FFmpeg():
             subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=13,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV={margin_v}'"
             bg_position_offset = (int(360) - 360//8) / 1.75
             background_cmd = f"drawbox=y=(ih-{int(360)}/2-{bg_position_offset}):color=yellow@1.0:width=iw:height={int(360)}/4:t=fill"
-
-            cls.asyncio_run_subprocess([
-                'ffmpeg',
-                '-loop', '1',
-                '-i', jpg_path,  # 输入的图片文件
-                '-i', pw_mp3_path,  # 输入的音频文件
-                '-c:v', 'libx264',  # 视频编码格式
-                '-t', str(pw_duration),  # 输出视频的持续时间,与音频持续时间相同
-                '-pix_fmt', 'yuv420p',  # 像素格式
-                '-c:a', 'aac',  # 音频编码格式
-                '-strict', 'experimental',  # 使用实验性编码器
-                '-shortest',  # 确保输出视频的长度与音频一致
-                '-vf', f"{background_cmd},{subtitle_cmd}",  # 视频过滤器,设置分辨率和其他过滤器
-                pw_url_path  # 输出的视频文件路径
-            ], timeout=500)
+            if "mp4" in jpg_path:
+                pw_path_txt = file_path + 'pw_path_video.txt'
+                with open(pw_path_txt, 'w') as f:
+                    f.write(f"file '{jpg_path}'\n")
+                cls.asyncio_run_subprocess([
+                    "ffmpeg",
+                    "-f", "concat",
+                    "-safe", "0",
+                    "-i", f"{pw_path_txt}",  # 视频序列输入的文本文件
+                    "-i", pw_mp3_path,  # 音频文件
+                    "-c:v", "libx264",  # 视频编码格式
+                    "-t", str(pw_duration),  # 输出视频的持续时间
+                    "-c:a", "aac",  # 音频编码格式
+                    "-b:v", "260k",  # 视频比特率
+                    "-b:a", "96k",  # 音频比特率
+                    "-threads", "2",  # 线程数
+                    "-vf", f"{background_cmd},{subtitle_cmd}",  # 视频过滤器(背景和字幕)
+                    "-map", "0:v:0",  # 映射视频流来自第一个输入文件(视频)
+                    "-map", "1:a:0",  # 映射音频流来自第二个输入文件(音频)
+                    "-y",  # 强制覆盖输出文件
+                    pw_url_path  # 输出文件路径
+                ], timeout=500)
+            else:
+                cls.asyncio_run_subprocess([
+                    'ffmpeg',
+                    '-loop', '1',
+                    '-i', jpg_path,  # 输入的图片文件
+                    '-i', pw_mp3_path,  # 输入的音频文件
+                    '-c:v', 'libx264',  # 视频编码格式
+                    '-t', str(pw_duration),  # 输出视频的持续时间,与音频持续时间相同
+                    '-pix_fmt', 'yuv420p',  # 像素格式
+                    '-c:a', 'aac',  # 音频编码格式
+                    '-strict', 'experimental',  # 使用实验性编码器
+                    '-shortest',  # 确保输出视频的长度与音频一致
+                    '-vf', f"{background_cmd},{subtitle_cmd}",  # 视频过滤器,设置分辨率和其他过滤器
+                    pw_url_path  # 输出的视频文件路径
+                ], timeout=500)
             if os.path.exists(pw_srt_path):
                 os.remove(pw_srt_path)
             return pw_url_path
@@ -345,7 +384,113 @@ class FFmpeg():
         return asyncio.run(run_subprocess())
 
 
+    @classmethod
+    def get_http_duration(cls, videos_path):
+        total_duration = 0
+        for video_path in videos_path:
+            url = "http://61.48.133.26:5555/api/v1/ffmpeg/get_meta"
+            payload = json.dumps({
+                "url": video_path,
+                "referer": ""
+            })
+            headers = {
+                'Authorization': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNGNhMTI4ZGYtYWMzMy00NWQ2LTg3MmEtMDAzOTk4MGVhM2ViIiwibmFtZSI6Inp5IiwiZXhwIjoyMDUwOTI3MjExfQ.k_rvuESjA62RgPDiLniVgJyLJn3Q8C1Y_AGq3CPRuKI',
+                'Content-Type': 'application/json'
+            }
+
+            try:
+                response = requests.request("POST", url, headers=headers, data=payload, timeout=30)
+                response =  response.json()
+                duration = response['data']['streams'][0]['duration']
+                total_duration += int(float(duration))
+            except Exception as e:
+                print(f"Error processing {video_path}: {e}")
+        return total_duration
+
+
 if __name__ == '__main__':
-    FFmpeg.video_png("/Users/z/Downloads/c2ce4ba6-fdb3-4e1b-bdba-dc05cb292abfvideo.mp4", "/Users/z/Downloads/")
+    file_path = '/Users/z/Downloads/478de0b6-4e52-44a5-a5d4-967b2cf8ce49'
+    jpg_path = '/Users/z/Downloads/478de0b6-4e52-44a5-a5d4-967b2cf8ce49rg_pixelvideo.mp4'
+    mp3_path='/Users/z/Downloads/478de0b6-4e52-44a5-a5d4-967b2cf8ce49pw_video.mp3'
+    pw_srt = """1
+00:00:00,000 --> 00:00:02,842
+这个视频揭示了中国近代历史上
+
+2
+00:00:02,842 --> 00:00:05,685
+一个鲜为人知却又极为重要的故
+
+3
+00:00:05,685 --> 00:00:05,888
+事
+
+4
+00:00:05,888 --> 00:00:07,106
+真是让人震惊
+
+5
+00:00:07,106 --> 00:00:07,715
+看完后
+
+6
+00:00:07,715 --> 00:00:10,354
+我不禁对历史有了更深的思考
+
+7
+00:00:10,354 --> 00:00:12,588
+让我们一起重温这段历史
+
+8
+00:00:12,588 --> 00:00:14,212
+提醒自己珍惜当下
+
+9
+00:00:14,212 --> 00:00:17,055
+我相信很多朋友也会对这个话题
+
+10
+00:00:17,055 --> 00:00:17,664
+感兴趣
+
+11
+00:00:17,664 --> 00:00:20,506
+请把这个视频分享到你们的群聊
+
+12
+00:00:20,506 --> 00:00:20,709
+中
+
+13
+00:00:20,709 --> 00:00:22,740
+让更多人了解这段历史
+
+14
+00:00:22,820 --> 00:00:23,824
+共鸣与反思
+
+15
+00:00:23,824 --> 00:00:25,430
+是我们共同的责任
+
+16
+00:00:25,430 --> 00:00:28,242
+也许我们能从中汲取更多的智慧
+
+17
+00:00:28,242 --> 00:00:28,844
+与力量
+
+18
+00:00:28,844 --> 00:00:29,848
+快动动手指
+
+19
+00:00:29,848 --> 00:00:32,659
+让我们一起分享这段重要的历史
+
+20
+00:00:32,659 --> 00:00:32,860
+吧"""
+    FFmpeg.pw_video(jpg_path, file_path, mp3_path, pw_srt)
 
 

+ 36 - 0
data_channel/piaoquan.py

@@ -1,3 +1,5 @@
+import json
+import time
 
 import requests
 from urllib.parse import urlencode
@@ -46,3 +48,37 @@ class PQ:
             new_video_id = data["data"]["id"]
             return new_video_id
         return None
+
+    @classmethod
+    def get_pq_oss(cls, video_id_list):
+        url_list = []
+        for video_id in video_id_list:
+            try:
+                url = "https://longvideoapi.piaoquantv.com/longvideoapi/openapi/video/getBaseInfo"
+
+                payload = json.dumps({
+                    "videoId": int(video_id)
+                })
+                headers = {
+                    'Content-Type': 'application/json',
+                    'Cookie': 'JSESSIONID=658158EABFCF6AC9B9BB0D8B61897A88'
+                }
+
+                response = requests.request("POST", url, headers=headers, data=payload, timeout=10)
+                response = response.json()
+                code = response['code']
+                if code == 0:
+                    data = response['data']
+                    video_path = data["videoPath"]
+                    url_list.append(f"http://rescdn.yishihui.com/{video_path}")
+                    time.sleep(1)
+                continue
+            except Exception as e:
+                time.sleep(1)
+                continue
+        return url_list
+
+
+if __name__ == '__main__':
+    rg_pw = "47969744,47969804,47969813,47969815,47969816"
+    PQ.get_pq_oss(rg_pw)