视频相关批量处理

本文最后更新于:2022年9月21日 凌晨

视频相关批量处理

1.字幕繁简转换

看剧偶尔遇到Netflix只提供了繁体字幕的情况,记录一下使用python批量转换为简体。

使用zhconv库的convert方法。有以下可供选择:

  • zh-cn 大陆简体

  • zh-sg 马新简体(马来西亚和新加坡使用的简体汉字)

  • zh-tw 台灣正體(台湾正体)
  • zh-hk 香港繁體(香港繁体)
  • zh-hans 简体
  • zh-hant 繁體(繁体)

代码如下:

1
2
3
4
5
6
7
from zhconv import convert

lines = open("1.srt", "r").readlines()
lines = [convert(line, "zh-cn") for line in lines]

with open('2.srt', 'w') as f:
f.writelines(lines)

2.字幕翻译

网易见外平台、飞书妙记等平台都提供了翻译字幕的功能,但是需要人工一个个上传,大批量操作不方便。可以使用百度翻译接口,注册开发者账号实名认证后每月有100万字符免费使用额度,足够正常使用。

参照官网给出的接口手册,接口python代码如下。需要requestsrandomhashlibjson库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def trans(q: str) -> str:
url = 'http://api.fanyi.baidu.com/api/trans/vip/translate'

_q = q.encode('utf-8') # 手册要求使用utf-8编码
_from = 'auto'
_to = 'en' # 你要转换成的语言
_appid = '你的百度开发者账号'
_salt = str(random.randint(123456789, 999999999)) # 为了密钥安全必须加盐
_sign = hashlib.md5((_appid + q + _salt + '你的百度开发者密钥').encode('utf-8')).hexdigest()

params = {
'q': _q,
'from': _from,
'to': _to,
'appid': _appid,
'salt': _salt,
'sign': _sign
}

response = requests.get(url=url, params=params).content
english = json.loads(response)
return english['trans_result'][0]['dst']

3.统计所有视频总时长

有时整个文件夹下载下来,文件夹套文件夹,结构很复杂,不知道哪年内能看完。这时候,可以用ffprobe统计视频总时长。需要电脑中安装ffprobe并添加到环境变量(安装过ffmpeg一般会自动安装此依赖项)。

注意到有些视频文件元数据受损(尤其是HLS流爬虫下载下来的视频),使用任何方法直接读取视频时长都会报错。使用try...catch...语法直接忽略。

整个python脚本如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/python3
import sys
import os
import subprocess

def get_duration(video_path: str):
ext = os.path.splitext(video_path)[-1]
good_format = ['.mp4', '.avi', '.flv', '.ts']
if ext not in good_format:
print("格式不支持")
return 0
ffprobe_cmd = 'ffprobe -i {} -show_entries format=duration -v quiet -of csv="p=0"'
p = subprocess.Popen(
ffprobe_cmd.format(video_path),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
out, err = p.communicate()
duration_seconds = float(str(out, 'utf-8').strip())
return int(duration_seconds)

all_files = []
def walkdir(path: str):
filelist = os.listdir(path)
for filename in filelist:
filepath = os.path.join(path, filename)
if os.path.isdir(filepath):
walkdir(filepath)
else:
all_files.append(filepath)

if __name__ == "__main__":
dir = sys.argv[1]
all_time = 0
if os.path.isdir(dir):
walkdir(str(dir))
for i in all_files:
print(i)
try:
time = get_duration(i)
except Exception as e:
print(e, '文件受损,无法计算\n')
time = 0
if time != 0:
print(time)
all_time += time
elif os.path.isfile(dir):
print(dir)
try:
time = get_duration(dir)
except Exception as e:
print(e, '文件受损,无法计算\n')
time = 0
all_time += time
else:
print("Are You OK?")
print(all_time // 3600, all_time % 3600 // 60, all_time % 60)

使用方法:将脚本直接拖到cmd(Windows)terminal(macOS)中,随后拖入要统计时长的文件夹,按回车即可。如果没有可执行权限请赋予。

也可以使用alias命令将脚本绝对路径命名为一个常用指令,方便地计算所有视频时长。

4.无损合并视频

有些视频爬虫爬下来是分段的,使用ffmpeg无损合并不会重新编码,较快。此方法只适用于mpeg容器。

1
2
3
4
5
6
# 首先生成一个文件列表(POSIX)
printf "file '%s'\n" *.mp4 > merge.txt
# windows用这个指令生成列表
(for %i in (*.mp4) do @echo file '%i') > merge.txt
# 使用ffmpeg合并
ffmpeg -f concat -safe 0 -i merge.txt -c copy out.mp4

5.视频添加黑边

使用topaz video enhance对一些视频进行超分辨率时,不合适的分辨率可能使软件直接闪退。使用ffmpeg提前处理一次黑边可以解决这个问题。

1
2
3
4
# 加黑边。添加右下。10线程,音频不重编码,无损质量视频编码
ffmpeg -threads 10 -i 1.mp4 -vf 'pad=目标列数:目标行数:右移列数:下移行数:颜色(默认black)' -acodec copy -crf 17 2.mp4
# 去黑边。切掉右下。10线程,音频不重编码,无损质量视频编码
ffmpeg -threads 10 -i 1.mp4 -vf 'crop=目标列数:目标行数:左移列数:上移行数' -acodec copy -crf 17 2.mp4


参考链接

  1. python汉字简繁体转换方法
  2. 通用翻译API接入文档
  3. ffmpeg获取视频时长和分辨率
  4. FFMPEG合并视频文件(无损)

本博客所有文章除特别声明外均为原创,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!