File: ffprobe.py

package info (click to toggle)
devede 4.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, stretch
  • size: 3,864 kB
  • sloc: python: 5,416; makefile: 17
file content (154 lines) | stat: -rw-r--r-- 6,115 bytes parent folder | download
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3

# Copyright 2014 (C) Raster Software Vigo (Sergio Costas)
#
# This file is part of DeVeDe-NG
#
# DeVeDe-NG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# DeVeDe-NG is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

import subprocess
import devedeng.configuration_data
import devedeng.executor
import os
import json

class ffprobe(devedeng.executor.executor):

    supports_analize = True
    supports_play = False
    supports_convert = False
    supports_menu = False
    supports_mkiso = False
    supports_burn = False
    display_name = "FFPROBE"

    @staticmethod
    def check_is_installed():
        try:
            handle = subprocess.Popen(["ffprobe","-h"], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
            (stdout, stderr) = handle.communicate()
            if 0==handle.wait():
                return True
            else:
                return False
        except:
            return False

    def __init__(self):

        devedeng.executor.executor.__init__(self)
        self.config = devedeng.configuration_data.configuration.get_config()

    def process_stdout(self,data):
        return

    def process_stderr(self,data):
        return

    def get_film_data(self, file_name):
        """ processes a file, refered by the FILE_MOVIE movie object, and fills its
            main data (resolution, FPS, length...) """

        self.original_file_size = os.path.getsize(file_name)

        command_line = ["ffprobe",file_name,"-of","json","-show_streams", "-loglevel", "quiet"]

        (stdout, stderr) = self.launch_process(command_line, False)
        try:
            stdout2 = stdout.decode("utf-8")
        except:
            stdout2 = stdout.decode("latin1")
        self.config.append_static_log("FFProbe JSON data: "+str(stdout2))
        return self.process_json(file_name,stdout2)


    def process_json(self,file_name,stdout2):

        self.audio_list=[]
        self.audio_streams = 0
        self.video_list=[]
        self.video_streams = 0
        self.original_width = 0
        self.original_height = 0
        self.original_length = -1
        self.original_videorate = 0
        self.original_audiorate = 0
        self.original_audiorate_uncompressed = 0
        self.original_fps = 0
        self.original_aspect_ratio = 0

        self.config.append_static_log("Getting data for {:s} with ffprobe".format(file_name))
        try:
            video_data = json.loads(stdout2)
        except:
            return True # There was an error reading the JSON data

        if not("streams" in video_data):
            return True # There are no streams!!!!!

        for element in video_data["streams"]:

            if (self.original_length == -1) and ("duration" in element):
                try:
                    self.original_length = int(float(element["duration"]))
                except:
                    self.original_length = -1

            if (element["codec_type"]=="video"):
                self.video_streams += 1
                self.video_list.append(element["index"])
                if (self.video_streams == 1):
                    self.original_width = int(float(element["width"]))
                    self.original_height = int(float(element["height"]))
                    if ("bit_rate" in element):
                        self.original_videorate = int(float(element["bit_rate"]))/1000
                    self.original_fps = self.get_division(element["avg_frame_rate"])
                    if ("display_aspect_ratio" in element):
                        self.original_aspect_ratio = self.get_division(element["display_aspect_ratio"])

            elif (element["codec_type"]=="audio"):
                self.audio_streams += 1
                self.audio_list.append(element["index"])
                if (self.audio_streams == 1):
                    if ("bit_rate" in element):
                        self.original_audiorate = int(float(element["bit_rate"]))/1000
                    self.original_audiorate_uncompressed = int(float(element["sample_rate"]))

        self.original_size = str(self.original_width)+"x"+str(self.original_height)
        if (self.original_aspect_ratio is None) or (self.original_aspect_ratio <= 1.0):
            if (self.original_height != 0):
                self.original_aspect_ratio = (float(self.original_width))/(float(self.original_height))

        if (self.original_aspect_ratio is not None):
            self.original_aspect_ratio = (float(int(self.original_aspect_ratio*1000.0)))/1000.0

        if (len(self.video_list) == 0):
            return True # the file is not a video file; maybe an audio-only file or another thing

        if self.original_length == -1: # if it was unable to detect the duration, try to use the human readable format
            command_line = ["ffprobe",file_name]
            (stdout, stderr) = self.launch_process(command_line, False)
            try:
                stdout2 = stdout.decode("utf-8") + "\n" + stderr.decode("utf-8")
            except:
                stdout2 = stdout.decode("latin1") + "\n" + stderr.decode("latin1")
            self.config.append_static_log("Using ffprobe human readable format: "+str(stdout2))
            for line in stdout2.split("\n"):
                line = line.strip()
                if line.startswith("Duration: "):
                    self.original_length = self.get_time(line[10:])
                    break

        self.config.append_static_log("Estimated length: {:d}; Resolution: {:s}".format(self.original_length,self.original_size))
        return False # no error