|
@@ -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)
|
|
|
|
|
|
|