Skip to content

Commit 6354d2d

Browse files
committed
新增翻译、YouTube上传、ffmpeg命令
1 parent 4e82876 commit 6354d2d

File tree

21 files changed

+3144
-3
lines changed

21 files changed

+3144
-3
lines changed

007-CutVideoAudio/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# FFmpeg批量剪切音视频
22

3+
[V2版本脚本](ff_util_v2.py)更加完善,但是未接入GUI
4+
35
本项目主要通过ffmpeg工具进行批量视频剪辑,随机剪辑,从而躲过自媒体平台的检查,从而达到一份视频多个账号运营。
46

57
使用前提:**必须要安装ffmpeg程序**,安装过程请自行百度。

007-CutVideoAudio/ff_util_v2.py

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
"""
4+
@Description:ff_util.py ffmpeg截切命令工具
5+
@Date :2022/03/14
6+
@Author :xhunmon
7+
8+
"""
9+
import os
10+
import re
11+
import time
12+
from datetime import datetime, timedelta
13+
14+
15+
def get_va_infos(ff_file, src):
16+
"""
17+
获取视频的基本信息
18+
@param ff_file: ffmpeg路径
19+
@param src: 视频路径
20+
@return: 结果:{'duration': '00:11:26.91', 'bitrate': '507', 'v_codec': 'h264', 'v_size': '1280x720', 'v_bitrate': '373', 'v_fps': '25', 'a_codec': 'aac', 'a_bitrate': '128'}
21+
"""
22+
cmd = r'{} -i "{}" -hide_banner 2>&1'.format(ff_file, src)
23+
output = os.popen(cmd).read()
24+
lines = output.splitlines()
25+
result = {}
26+
for line in lines:
27+
if line.strip().startswith('Duration:'):
28+
result['duration'] = line.split(',')[0].split(': ')[-1]
29+
result['bitrate'] = line.split(',')[-1].strip().split(': ')[-1].split(' ')[0]
30+
elif line.strip().startswith('Stream #0'):
31+
line = re.sub(r'\[.*?\]', '', re.sub(r'\(.*?\)', '', line))
32+
if 'Video' in line:
33+
result['v_codec'] = line.split(',')[0].split(': ')[-1].strip()
34+
result['v_size'] = line.split(',')[2].strip().split(' ')[0].strip()
35+
result['v_bitrate'] = line.split(',')[3].strip().split(' ')[0].strip()
36+
result['v_fps'] = line.split(',')[4].strip().split(' ')[0].strip()
37+
elif 'Audio' in line:
38+
result['a_codec'] = line.split(',')[0].split(': ')[-1].strip()
39+
result['a_bitrate'] = line.split(',')[4].strip().split(' ')[0].strip()
40+
print(result)
41+
return result
42+
43+
44+
def get_duration(ff_file, src):
45+
'''
46+
执行命令获取输出这样的:Duration: 00:00:31.63, start: 0.000000, bitrate: 1376 kb/s
47+
:param ff_file: ffmpeg程序路径
48+
:param src: 音视频文件
49+
:return: 返回毫秒
50+
'''
51+
cmd = r'{} -i "{}" 2>&1 | grep "Duration"'.format(ff_file, src)
52+
info = os.popen(cmd).read()
53+
dur = info.split(',')[0].replace(' ', '').split(':')
54+
h, m, ss = int(dur[1]) * 60 * 60 * 1000, int(dur[2]) * 60 * 1000, dur[3]
55+
if '.' in ss:
56+
s1 = ss.split('.')
57+
s = int(s1[0]) * 1000 + int(s1[1]) * 10
58+
else:
59+
s = int(ss) * 1000
60+
return h + m + s
61+
62+
63+
def format_h_m_s(t):
64+
return f'0{t}' if t < 10 else f'{t}'
65+
66+
67+
def format_ms(t):
68+
if t < 10:
69+
return f'00{t}'
70+
return f'0{t}' if t < 100 else f'{t % 1000}'
71+
72+
73+
def format_to_time(ms):
74+
'''
75+
毫秒 --> 'xx:xx:xx.xxx'
76+
:param ms: 毫秒
77+
:return: 'xx:xx:xx.xxx'
78+
'''
79+
# t = timedelta(milliseconds=ms)
80+
# return str(t)
81+
h = format_h_m_s(int(ms / 1000 / 60 / 60))
82+
m = format_h_m_s(int(ms / 1000 / 60 % 60))
83+
s = format_h_m_s(int(ms / 1000 % 60))
84+
m_s = format_ms(int(ms % 1000))
85+
return '{}:{}:{}.{}'.format(h, m, s, m_s)
86+
87+
88+
def format_to_ms(duration: str):
89+
"""
90+
'xx:xx:xx.xxx' --> 毫秒
91+
@param duration: 时间长度'xx:xx:xx.xxx'
92+
@return: 毫秒
93+
"""
94+
hms = duration.split(':')
95+
s_str = hms[2]
96+
ms_str = '0'
97+
if '.' in s_str:
98+
s_ms = s_str.split('.')
99+
s_str = s_ms[0]
100+
ms_str = s_ms[1]
101+
h = int(hms[0]) * 1000 * 60 * 60
102+
m = int(hms[1]) * 1000 * 60
103+
s = int(s_str) * 1000
104+
ms = int(ms_str)
105+
return h + m + s + ms
106+
107+
108+
def srt_to_ass(ff_file, src, dst):
109+
os.system(f'{ff_file} -i {src} {dst}')
110+
111+
112+
def cut_with_subtitle(ff_file, src, dst, srt, width, height, margin_v, font_size=50, dur_full: str = None,
113+
start='00:00:00.000', tail='00:00:00.000', fps=None,
114+
v_bit=None, a_bit=None):
115+
"""
116+
添加硬字幕:ffmpeg -i "../output/733316.mp4" -ss "00:02:00" -t 10 -r 23 -b:v 400K -c:v libx264 -b:a 38K -c:a aac -vf "subtitles=../output/input.ass:force_style='PlayResX=1280,PlayResY=720,MarginV=80,Fontsize=50'" ../output/ass.mp4
117+
"""
118+
t_start = time.time()
119+
dur_ms = format_to_ms(dur_full) - format_to_ms(tail) - format_to_ms(start)
120+
dur = format_to_time(dur_ms)
121+
122+
filename, ext = os.path.splitext(srt)
123+
ass = f'{filename}.ass'
124+
if os.path.exists(ass):
125+
os.remove(ass)
126+
ass_cmd = '{} -i "{}" "{}"'.format(ff_file, srt, ass)
127+
print(ass_cmd)
128+
os.system(ass_cmd)
129+
# ffmpeg -i "input.mp4" -ss "00:02:10.000" -t 12397 -r 15 -b:v 500K -c:v libx264 -c:a aac
130+
cmd = '{} -i "{}"'.format(ff_file, src)
131+
cmd = '{} -ss "{}" -t {}'.format(cmd, start, int(format_to_ms(dur) / 1000))
132+
if fps: # 添加裁剪的fps
133+
cmd = '{} -r {}'.format(cmd, fps)
134+
# -c copy 不经过解码,会出现黑屏,因为有可能是P帧和B帧
135+
if v_bit: # 添加视频bitrate,并且指定用libx264进行编码(ffmpeg必须安装)
136+
cmd = '{} -b:v {}K -c:v libx264'.format(cmd, v_bit)
137+
if a_bit: # 添加音频bitrate,并且指定用aac进行编码
138+
cmd = '{} -b:a {}K -c:a aac'.format(cmd, a_bit)
139+
# -vf "subtitles=input.ass:force_style='PlayResX=1280,PlayResY=720,MarginV=70,Fontsize=50'"
140+
style = "PlayResX={},PlayResY={},MarginV={},Fontsize={}".format(width, height, margin_v, font_size)
141+
sub_file = "{}".format(ass)
142+
cmd = '''{} -vf "subtitles={}:force_style='{}'"'''.format(cmd, sub_file, style)
143+
# cmd = f'{cmd} -vf "subtitles={ass}:force_style="""PlayResX={width},PlayResY={height},MarginV={margin_v},Fontsize={font_size}""""'
144+
cmd = '{} {}'.format(cmd, dst)
145+
print(cmd)
146+
if os.path.exists(dst):
147+
os.remove(dst)
148+
os.system(cmd)
149+
os.remove(ass)
150+
print('一共花了 {} 秒 进行裁剪并添加字幕 {}'.format(int(time.time() - t_start), src))
151+
152+
153+
def cut_va_full(ff_file, src, dst, dur: str = None, start='00:00:00.000', fps=None, v_bit=None, a_bit=None,
154+
copy_a=False):
155+
"""
156+
ffmpeg -i "input.mp4" -ss "00:02:10.000" -t 12397 -r 15 -b:v 500K -c:v libx264 -c:a aac "凡人修仙传1重制版-国创-高清独家在线观看-bilibili-哔哩哔哩.mp4"
157+
其他所有的视频裁剪命令都需要通过这个实现
158+
@param ff_file: ffmpeg路径
159+
@param src: 输入路径
160+
@param dst: 输出路径
161+
@param dur: 裁剪长度,格式为'00:00:00.000'
162+
@param start: 裁剪的起点,如果dur=None,表示需要对时间进行裁剪,只是转换格式罢了
163+
@param fps: 帧率,通常视频15~18帧即可,动漫一般24帧
164+
@param v_bit: 单独控制视频的比特率
165+
@param a_bit: 单独控制音频的比特率
166+
@param copy_a: 直接复制音频通道数据,当 a_bit=None方有效
167+
"""
168+
cmd = '{} -i "{}"'.format(ff_file, src) # 输入文件
169+
if dur is not None: # 添加裁剪时间
170+
cmd = '{} -ss "{}" -t {}'.format(cmd, start, int(format_to_ms(dur) / 1000))
171+
if fps: # 添加裁剪的fps
172+
cmd = '{} -r {}'.format(cmd, fps)
173+
# -c copy 不经过解码,会出现黑屏,因为有可能是P帧和B帧
174+
if v_bit: # 添加视频bitrate,并且指定用libx264进行编码(ffmpeg必须安装)
175+
cmd = '{} -b:v {}K -c:v libx264'.format(cmd, v_bit)
176+
if a_bit: # 添加音频bitrate,并且指定用aac进行编码
177+
cmd = '{} -b:a {}K -c:a aac'.format(cmd, a_bit)
178+
elif copy_a: # 是否完全复制音频
179+
cmd = '{} -c:a copy'.format(cmd)
180+
cmd = '{} "{}"'.format(cmd, dst) # 添加输出
181+
if os.path.exists(dst):
182+
os.remove(dst)
183+
t_start = time.time()
184+
os.system(cmd)
185+
print('一共花了 {} 秒 进行裁剪 {}'.format(int(time.time() - t_start), src))
186+
187+
188+
def cut_va_tail(ff_file, src, dst, dur_full: str = None, start='00:00:00.000', tail='00:00:00.000', fps=None,
189+
v_bit=None, a_bit=None, copy_a=False):
190+
"""
191+
裁剪头尾
192+
"""
193+
dur_ms = format_to_ms(dur_full) - format_to_ms(tail) - format_to_ms(start)
194+
dur = format_to_time(dur_ms)
195+
cut_va_full(ff_file, src, dst, dur, start, fps, v_bit, a_bit, copy_a)
196+
197+
198+
def cut_audio(ff_file, src, start, dur, dst):
199+
'''
200+
裁剪一段音频进行输出
201+
:param ff_file: ffmpeg程序路径
202+
:param src: 要裁剪的文件路径,可以是视频文件
203+
:param start: 开始裁剪点,单位毫秒开始
204+
:param dur: 裁剪时长,单位秒
205+
:param dst: 输出路径,包括后缀名
206+
:return:
207+
'''
208+
if os.path.exists(dst):
209+
os.remove(dst)
210+
os.system(
211+
r'{} -i "{}" -vn -acodec copy -ss {} -t {} "{}"'.format(ff_file, src, format_to_time(start), dur, dst))
212+
213+
214+
def cut_video(ff_file, src, start, dur, fps, bit, dst):
215+
'''
216+
裁剪一段视频进行输出, -ss xx:xx:xx.xxx
217+
:param ff_file: ffmpeg程序路径
218+
:param src: 要裁剪的文件路径,可以是视频文件
219+
:param start: 开始裁剪点,单位毫秒开始
220+
:param dur: 裁剪时长,单位秒
221+
:param fps: 帧率,通常是25~30
222+
:param bit: 比特率,通常是1600~2000即可
223+
:param dst: 输出路径,包括后缀名
224+
:return:
225+
'''
226+
if os.path.exists(dst):
227+
os.remove(dst)
228+
os.system(
229+
r'{} -i "{}" -ss {} -t {} -r {} -b:v {}K -an "{}"'.format(ff_file, src, format_to_time(start), dur, fps,
230+
bit, dst))
231+
232+
233+
def cut_va_dur(ff_file, src, dst, start=0, dur=0, fps=None, bit=None):
234+
"""
235+
根据头尾裁剪视频
236+
:param ff_file: ffmpeg工具
237+
:param src: 输入资源
238+
:param dst: 输出文件
239+
:param start: 起点
240+
:param end: 终点
241+
:param fps: 帧率
242+
:param bit: 比特率
243+
:return:
244+
"""
245+
length = get_duration(ff_file, src)
246+
if start + dur > length:
247+
print('裁剪比视频长')
248+
return
249+
if os.path.exists(dst):
250+
os.remove(dst)
251+
252+
cmd = r'{} -i "{}"'.format(ff_file, src)
253+
cmd = cmd + ' -ss {}'.format(format_to_time(start))
254+
cmd = cmd + ' -t {}'.format(format_to_time(dur))
255+
if fps:
256+
cmd = cmd + ' -r {}'.format(fps)
257+
if bit:
258+
cmd = cmd + ' -b:v {}K'.format(bit)
259+
cmd = cmd + ' -c:v libx264 "{}"'.format(dst) # 使用x264解码后重新封装
260+
# cmd = cmd+' -c copy {}'.format(dst) #不经过解码,会出现黑屏
261+
os.system(cmd)
262+
263+
264+
def cut_va_start_end(ff_file, src, dst, start='00:00:00', end='00:00:00', dur='00:00:00', fps=None, bit=None):
265+
dur = format_to_ms(dur) - format_to_ms(end)
266+
cmd = f'{ff_file} -i "{src}" -ss {start} -t {dur} -c copy "{dst}"'
267+
if os.path.exists(dst):
268+
os.remove(dst)
269+
os.system(cmd)
270+
271+
272+
def cut_va_end(ff_file, src, dst, start=0, end=0, fps=None, bit=None):
273+
"""
274+
根据头尾裁剪视频
275+
:param ff_file: ffmpeg工具
276+
:param src: 输入资源
277+
:param dst: 输出文件
278+
:param start: 起点
279+
:param end: 终点
280+
:param fps: 帧率
281+
:param bit: 比特率
282+
:return:
283+
"""
284+
length = get_duration(ff_file, src)
285+
dur = length - (start + end)
286+
if dur <= 0:
287+
print('裁剪比视频长')
288+
return
289+
cut_va_dur(ff_file, src, dst, start, dur, fps, bit)
290+
291+
292+
def muxer_va(ff_file, src_v, src_a, dst):
293+
if os.path.exists(dst):
294+
os.remove(dst)
295+
os.system(r'{} -i "{}" -i "{}" -c:v copy -c:a aac -strict experimental "{}"'.format(ff_file, src_v, src_a, dst))

009-Translate/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 多平台免费翻译神器
2+
3+
## 1. 输入框翻译
4+
5+
直接在输入框输入内容,选择目标语言,翻译平台即可。
6+
7+
8+
## 2.文件翻译
9+
10+
- 1.支持txt翻译,但是文本内容不宜过大
11+
12+
- 2.支持html翻译
13+
14+
- 3.定制版srt字幕文件翻译,自定义修改[load_srt.py](load_srt.py)
15+
16+
- 4.其他文本文件也是可以的,但是肯定有bug
17+
18+
19+
## 3.打包应用程序
20+
21+
可以自行打包 exe和Mac平台的app。打包脚本参考[doc/pyinstall.sh](doc/pyinstaller.sh),注意window平台的路径反斜杠更改。
22+
23+
24+
> 主要引入:translators

0 commit comments

Comments
 (0)