|
@@ -1,17 +1,7 @@
|
|
|
-import configparser
|
|
|
-import glob
|
|
|
-import os
|
|
|
-import random
|
|
|
-import re
|
|
|
+
|
|
|
import subprocess
|
|
|
-import sys
|
|
|
import time
|
|
|
-import urllib.parse
|
|
|
-import json
|
|
|
|
|
|
-import requests
|
|
|
-from datetime import datetime, timedelta
|
|
|
-from urllib.parse import urlencode
|
|
|
|
|
|
class FFmpeg():
|
|
|
|
|
@@ -60,12 +50,9 @@ class FFmpeg():
|
|
|
output_video_path = ''
|
|
|
try:
|
|
|
# 获取视频的原始宽高信息
|
|
|
- ffprobe_cmd = f"ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 {video_url}"
|
|
|
- ffprobe_process = subprocess.Popen(ffprobe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
|
- output, _ = ffprobe_process.communicate()
|
|
|
- width, height = map(int, output.decode().strip().split(','))
|
|
|
+ width, height = cls.get_w_h_size(video_url)
|
|
|
# 计算裁剪后的高度
|
|
|
- new_height = int(height * 0.7)
|
|
|
+ new_height = int(height * 0.8)
|
|
|
# 构建 FFmpeg 命令,裁剪视频高度为原始高度的70%,并将宽度缩放为320x480
|
|
|
ffmpeg_cmd = [
|
|
|
"ffmpeg",
|
|
@@ -82,13 +69,24 @@ class FFmpeg():
|
|
|
except Exception as e:
|
|
|
return None
|
|
|
|
|
|
+ """
|
|
|
+ 获取视频宽高
|
|
|
+ """
|
|
|
+ @classmethod
|
|
|
+ def get_w_h_size(cls, new_video_path):
|
|
|
+ # 获取视频的原始宽高信息
|
|
|
+ ffprobe_cmd = f"ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 {new_video_path}"
|
|
|
+ ffprobe_process = subprocess.Popen(ffprobe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
|
+ output, _ = ffprobe_process.communicate()
|
|
|
+ height, width = map(int, output.decode().strip().split(','))
|
|
|
+ return width, height
|
|
|
+
|
|
|
"""
|
|
|
视频裁剪
|
|
|
"""
|
|
|
@classmethod
|
|
|
def video_crop(cls, new_video_path, video_path_url, pw_random_id):
|
|
|
crop_url = video_path_url + str(pw_random_id) + 'crop.mp4'
|
|
|
-
|
|
|
# 获取视频的原始宽高信息
|
|
|
ffprobe_cmd = f"ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 {new_video_path}"
|
|
|
ffprobe_process = subprocess.Popen(ffprobe_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
|
@@ -98,11 +96,11 @@ class FFmpeg():
|
|
|
# 计算裁剪后的高度
|
|
|
new_height = int(height * 0.8)
|
|
|
|
|
|
- # 构建 FFmpeg 命令,裁剪视频高度为原始高度的70%,并将宽度缩放为320x480
|
|
|
+ # 构建 FFmpeg 命令,裁剪视频高度为原始高度的80%
|
|
|
ffmpeg_cmd = [
|
|
|
"ffmpeg",
|
|
|
"-i", new_video_path,
|
|
|
- "-vf", f"crop={width}:{new_height},scale=320:480",
|
|
|
+ "-vf", f"crop={width}:{new_height}",
|
|
|
"-c:v", "libx264",
|
|
|
"-c:a", "aac",
|
|
|
"-y",
|
|
@@ -142,6 +140,8 @@ class FFmpeg():
|
|
|
:param new_video_path: 视频地址
|
|
|
:return:
|
|
|
"""
|
|
|
+ # 获取视频的原始宽高信息
|
|
|
+ width, height = cls.get_w_h_size(new_video_path)
|
|
|
jpg_url = video_path_url + str(pw_random_id) + 'png.jpg'
|
|
|
# 获取视频时长
|
|
|
total_duration = cls.get_video_duration(new_video_path)
|
|
@@ -149,7 +149,7 @@ class FFmpeg():
|
|
|
# 获取视频最后一秒,生成.jpg
|
|
|
subprocess.run(
|
|
|
['ffmpeg', '-ss', str(time_offset), '-i', new_video_path, '-t', str(total_duration), '-vf', 'fps=1', "-y", jpg_url])
|
|
|
- return jpg_url
|
|
|
+ return jpg_url, height
|
|
|
|
|
|
"""
|
|
|
获取视频音频
|
|
@@ -173,7 +173,7 @@ class FFmpeg():
|
|
|
生成片尾视频
|
|
|
"""
|
|
|
@classmethod
|
|
|
- def pw_video(cls, jpg_url, video_path_url, pw_url, pw_srt, pw_random_id, pw_mp3_path):
|
|
|
+ def pw_video(cls, jpg_url, video_path_url, pw_url, pw_srt, pw_random_id, pw_mp3_path, height):
|
|
|
# 添加音频到图片
|
|
|
"""
|
|
|
jpg_url 图片地址
|
|
@@ -192,11 +192,10 @@ class FFmpeg():
|
|
|
pw_url_path = video_path_url + str(pw_random_id) + 'pw_video.mp4'
|
|
|
# 获取视频时长
|
|
|
pw_duration = cls.get_video_duration(pw_url)
|
|
|
-
|
|
|
time.sleep(2)
|
|
|
# 添加字幕 wqy-zenhei Hiragino Sans GB
|
|
|
- subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV=155'"
|
|
|
- background_cmd = "drawbox=y=366/2:color=yellow@1.0:width=iw:height=50:t=fill"
|
|
|
+ subtitle_cmd = f"subtitles={pw_srt_path}:force_style='Fontsize=16,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV=135'"
|
|
|
+ background_cmd = f"drawbox=y=(ih-{int(height)}/2-{int(height)}/2):color=yellow@1.0:width=iw:height={int(height)}/4:t=fill"
|
|
|
ffmpeg_cmd = [
|
|
|
'ffmpeg',
|
|
|
'-loop', '1',
|
|
@@ -208,19 +207,20 @@ class FFmpeg():
|
|
|
'-c:a', 'aac', # 音频编码格式
|
|
|
'-strict', 'experimental', # 使用实验性编码器
|
|
|
'-shortest', # 确保输出视频的长度与音频一致
|
|
|
- '-vf', f"scale=320x480,{background_cmd},{subtitle_cmd}", # 视频过滤器,设置分辨率和其他过滤器
|
|
|
+ '-vf', f"{background_cmd},{subtitle_cmd}", # 视频过滤器,设置分辨率和其他过滤器
|
|
|
pw_url_path # 输出的视频文件路径
|
|
|
]
|
|
|
subprocess.run(ffmpeg_cmd)
|
|
|
return pw_url_path
|
|
|
|
|
|
-
|
|
|
"""
|
|
|
设置统一格式拼接视频
|
|
|
"""
|
|
|
@classmethod
|
|
|
def concatenate_videos(cls, video_list, video_path_url):
|
|
|
concatenate_videos_url = video_path_url + 'concatenate_videos.mp4'
|
|
|
+ # 获取视频的原始宽高信息
|
|
|
+ width, height = cls.get_w_h_size(video_list[0])
|
|
|
# 拼接视频
|
|
|
VIDEO_COUNTER = 0
|
|
|
FF_INPUT = ""
|
|
@@ -231,7 +231,7 @@ class FFmpeg():
|
|
|
# 添加输入文件
|
|
|
FF_INPUT += f" -i {videos}"
|
|
|
# 为每个视频文件统一长宽,并设置SAR(采样宽高比)
|
|
|
- FF_SCALE += f"[{VIDEO_COUNTER}:v]scale=320x480,setsar=1[v{VIDEO_COUNTER}];"
|
|
|
+ FF_SCALE += f"[{VIDEO_COUNTER}:v]scale={int(height)}x{int(width)},setsar=1[v{VIDEO_COUNTER}];"
|
|
|
# 为每个视频文件创建一个输入流,并添加到-filter_complex参数中
|
|
|
FF_FILTER += f"[v{VIDEO_COUNTER}][{VIDEO_COUNTER}:a]"
|
|
|
# 增加视频计数器
|
|
@@ -260,13 +260,17 @@ class FFmpeg():
|
|
|
f.write(f"file '{new_video_path}'\n")
|
|
|
with open(single_video_srt, 'w') as f:
|
|
|
f.write(f"1\n{start_time} --> {end_time}\n\u2764\uFE0F{zm}\n\n")
|
|
|
- background_cmd = "drawbox=y=370/1:color=yellow@1.0:width=iw:height=70:t=fill"
|
|
|
+ width, height = cls.get_w_h_size(new_video_path)
|
|
|
+ box_height = int(int(height) / 4) # 框的高度为视频高度的四分之一
|
|
|
+
|
|
|
+ background_cmd = f"drawbox=y=ih-{70 + box_height}-{int(box_height / 20)}:color=yellow@1.0:width=iw:height={box_height}:t=fill"
|
|
|
+
|
|
|
if video_share == '有':
|
|
|
# 添加字幕 wqy-zenhei Hiragino Sans GB
|
|
|
- subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV=30'"
|
|
|
+ subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=0,PrimaryColour=&H000000,SecondaryColour=&H000000,Bold=1,MarginV=20'"
|
|
|
draw = f"{background_cmd},{subtitle_cmd}"
|
|
|
else:
|
|
|
- subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=30'"
|
|
|
+ subtitle_cmd = f"subtitles={single_video_srt}:force_style='Fontsize=14,Fontname=wqy-zenhei,Outline=2,PrimaryColour=&H00FFFF,SecondaryColour=&H000000,Bold=1,MarginV=20'"
|
|
|
draw = f"{subtitle_cmd}"
|
|
|
# 多线程数
|
|
|
num_threads = 4
|
|
@@ -279,7 +283,7 @@ class FFmpeg():
|
|
|
"-c:v", "libx264",
|
|
|
"-c:a", "aac",
|
|
|
"-threads", str(num_threads),
|
|
|
- "-vf", f"scale=320x480,{draw}",
|
|
|
+ "-vf", f"{draw}",
|
|
|
"-y",
|
|
|
single_video_url
|
|
|
|