在Python中返回多个参数

时间:2018-03-07 09:29:40

标签: python function ffmpeg

我正在尝试使用函数重写我的一个脚本。它正在分析目录中的一对传输流文件,然后使用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)

3 个答案:

答案 0 :(得分:1)

在没有太多样板的情况下实现目标的一种方法是使用yield关键字和tuple

的组合

例如,您可以更改第一个函数中的最后一行:

return gop

为:

yield (gop, abs_file)

这将允许您从函数中一次返回多个值,并且每次执行此行时也会“生成”一个值。 'yield'关键字的作用是将您的函数转换为生成器。

此外,既然你要返回文件名,现在你需要在其他两个函数中迭代输入目录,这样你就可以删除write_gop_dataiframe_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)