我正在尝试使用函数重写我的一个脚本。它正在分析目录中的一对传输流文件,然后使用ffprobe返回所有TS文件的GoP大小,并将json文件写入日志目录。所以这最初是我的脚本,它运行得很好:
#!/usr/bin/env python
import subprocess
import json
import os.path
recdir = "/home/user/recordings/"
logdir = "/home/user/logs/"
for input_file in os.listdir(recdir):
gop_list = []
p = 0
fname = os.path.splitext(input_file)[0]
if input_file.endswith(".ts"):
abs_file = recdir + "/" + input_file
# Execute the ffprobe command for analysing the GoP Structure
gop_data = subprocess.check_output(['ffprobe', '-v', 'quiet', '-read_intervals', "%+10", '-print_format', 'json', '-select_streams', 'v', '-show_frames', '-show_entries', 'frame=coded_picture_number,key_frame,pict_type', abs_file])
# print gop_data
# Write output to a file
out = open("{}_gop_data.json".format(fname), "w+")
out.write(gop_data)
out.close
#End of writing
# Loading the json file
gop = json.loads(gop_data.decode('utf-8'))
print "-------------------------- GoP information for {} ------------------------------".format(input_file)
print
# Calculating the GoP length of the video(difference between two IDR frames)
for i in range(len(gop["frames"])):
if (gop["frames"][i]["pict_type"]) == "I" and (gop["frames"][i]["key_frame"] == 1):
gop_list.append(i)
p += 1
# Printing the first 5 results if present
for r in range(1, p):
print "GoP frame length Nr: {0} is: {1}".format(r, (gop_list[r] - gop_list[r-1] + 1))
print
for i in range(len(gop["frames"])):
if (gop["frames"][i]["pict_type"]) == "I" and (gop["frames"][i]["key_frame"] == 1):
gop_list.append(i)
p += 1
我想从中创建3个功能。一种是执行ffprobe命令并将输出保存到变量" gop"。另一个是将json输出写入不同的文件,第三个是将数据提供给命令行。目前的问题是第一个函数返回gop参数,但它只返回最后一个。请记住,这些文件非常大。所以我想我需要同时返回文件的名称和相应的GoP文件,并将这些数据用于其他两个函数(write_gop_data和iframe_calculator),但我不知道如何做到这一点。
#!/usr/bin/env python
import subprocess
import json
import os.path
recdir = "/home/user/recordings/"
logdir = "/home/user/logs/"
def reading_gop_data(input_directory):
for input_file in os.listdir(input_directory):
fname = os.path.splitext(input_file)[0]
if input_file.endswith(".ts"):
abs_file = recdir + input_file
# Execute the ffprobe command for analysing the GoP Structure
gop = subprocess.check_output(['ffprobe', '-v', 'quiet', '-read_intervals', "%+10", '-print_format', 'json', '-select_streams', 'v', '-show_frames', '-show_entries', 'frame=coded_picture_number,key_frame,pict_type', abs_file])
return gop
def write_gop_data(gop_data, input_directory, save_directory):
for input_file in os.listdir(input_directory):
fname = os.path.splitext(input_file)[0]
out = open("{}{}_gop.json".format(save_directory, fname), "w+")
out.write(gop_data)
out.close
def iframe_calculator(gop_data, input_directory):
for input_file in os.listdir(input_directory):
gop_list = []
p = 0
if input_file.endswith(".ts"):
gop_json = json.loads(gop_data.decode('utf-8'))
print "-------------------------- GoP information for {} ------------------------------".format(input_file)
print
# Calculating the GoP length of the video(difference between two IDR frames)
for i in range(len(gop_json["frames"])):
if (gop_json["frames"][i]["pict_type"]) == "I" and (gop_json["frames"][i]["key_frame"] == 1):
gop_list.append(i)
p += 1
# Printing the first 5 results if present
for r in range(1, p):
print "GoP frame length Nr: {0} is: {1}".format(r, (gop_list[r] - gop_list[r-1] + 1))
print
# reading_gop_data(recdir)
write_gop_data(reading_gop_data(recdir), recdir, logdir)
iframe_calculator(reading_gop_data(recdir), recdir)
答案 0 :(得分:1)
在没有太多样板的情况下实现目标的一种方法是使用yield关键字和tuple
的组合例如,您可以更改第一个函数中的最后一行:
return gop
为:
yield (gop, abs_file)
这将允许您从函数中一次返回多个值,并且每次执行此行时也会“生成”一个值。 'yield'关键字的作用是将您的函数转换为生成器。
此外,既然你要返回文件名,现在你需要在其他两个函数中迭代输入目录,这样你就可以删除write_gop_data
和iframe_calculator
下面的行。功能:
for input_file in os.listdir(input_directory):
然后,当您迭代记录数据时,您可以使用以下结构:
for gop_data in reading_gop_data(recdir):
gop, file_name = gop_data
print "Processing file: " + file_name
write_gop_data(gop, file_name, logdir)
iframe_calculator(gop, file_name)
在每次迭代中,gop_data
变量由reading_gop_data
函数填充,然后您可以将元组解压缩到执行其余处理所需的两个变量中。
答案 1 :(得分:0)
我认为你需要使用生成器功能。
def reading_gop_data(input_directory):
for input_file in os.listdir(input_directory):
fname = os.path.splitext(input_file)[0]
if input_file.endswith(".ts"):
abs_file = recdir + input_file
# Execute the ffprobe command for analysing the GoP Structure
gop = subprocess.check_output(['ffprobe', '-v', 'quiet', '-read_intervals', "%+10", '-print_format', 'json', '-select_streams', 'v', '-show_frames', '-show_entries', 'frame=coded_picture_number,key_frame,pict_type', abs_file])
yield gop
然后你可以用它来消费。
for gop in reading_gop_data(input_directory):
write_gop_data(gop)
答案 2 :(得分:0)
所以在第一个函数中我需要使用@sileknarf和@Rahul建议的yield函数,但是我需要返回3个参数:yield (gop, abs_file, fname)
如下所述,应该删除以下两个函数中的for循环。 @sileknarf和write_gop_data中的fname也必须删除。这两个函数应如下所示:
def write_gop_data(gop_data, input_directory, save_directory):
out = open("{}{}_gop.json".format(save_directory, fname), "w+")
out.write(gop_data)
out.close
def iframe_calculator(gop_data, input_directory):
gop_list = []
if input_file.endswith(".ts"):
gop_json = json.loads(gop_data.decode('utf-8'))
print "-------------------------- GoP information for {} ------------------------------".format(input_file)
print
# Calculating the GoP length of the video(difference between two IDR frames)
for i in range(len(gop_json["frames"])):
if (gop_json["frames"][i]["pict_type"]) == "I" and (gop_json["frames"][i]["key_frame"] == 1):
gop_list.append(i)
# Printing the first 5 results if present
for r in range(1, 5):
print "GoP frame length Nr: {} is: {}".format(r, (gop_list[r] - gop_list[r-1] + 1))
print
for gop_data in reading_gop_data(recdir):
gop, input_file, fname = gop_data
write_gop_data(gop, recdir, logdir)
iframe_calculator(gop, recdir)