示例#1
0
def detect_imagemagick(path):
    a = Invocation('identify -verbose {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout[0].split('\n')
    # Check for an actual mimetype first
    mimetype = None
    for line in result:
        line = line.lstrip(' ')
        if line.startswith('Mime type: '):
            mimetype = line[11:]
    if mimetype in [ 'image/png', 'image/jpeg' ]:
        return {
            'type': mimetype,
            'extra': None,
            'flags': None
        }
    # Check for SVG, it's special
    for line in result:
        line = line.lstrip(' ')
        if line ==  'Format: SVG (Scalable Vector Graphics)':
            return {
                'type': 'image/svg+xml',
                'extra': None,
                'flags': None
            }

    return {
        'type': 'image',
        'extra': None,
        'flags': None
    }
示例#2
0
def detect_interlacing(path):
    a = Invocation('ffmpeg -vf idet -vframes 100 -an -f rawvideo -y /dev/null -i {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return False
    result = a.stdout[1].split('\n')
    for line in result:
        print(line)
        if line.startswith('[Parsed_idet_'):
            match = re.search('TFF:([0-9]+) BFF:([0-9]+) Progressive:([0-9]+) Undetermined:([0-9]+)', line)
            if match == None:
                return False
            tff = float(match.group(1))
            bff = float(match.group(2))
            progressive = float(match.group(3))
            undetermined = float(match.group(4))
            total = tff + bff + progressive + undetermined
            if total == 0:
                return False
            tff = tff / total
            bff = bff / total
            progressive = progressive / total
            undetermined = undetermined / total
            if undetermined < 0.05 and progressive < 0.8:
                if tff >= 0.8 or bff >= 0.8:
                    # It's probably interlaced.
                    return True
    return False
示例#3
0
文件: detect.py 项目: imgrush/Imgrush
def detect_interlacing(path):
    a = Invocation(
        'ffmpeg -vf idet -vframes 100 -an -f rawvideo -y /dev/null -i {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return False
    result = a.stdout[1].split('\n')
    for line in result:
        if line.startswith('[Parsed_idet_'):
            match = re.search(
                'TFF:([0-9]+) BFF:([0-9]+) Progressive:([0-9]+) Undetermined:([0-9]+)',
                line)
            if match == None:
                return False
            tff = float(match.group(1))
            bff = float(match.group(2))
            progressive = float(match.group(3))
            undetermined = float(match.group(4))
            total = tff + bff + progressive + undetermined
            if total == 0:
                return False
            tff = tff / total
            bff = bff / total
            progressive = progressive / total
            undetermined = undetermined / total
            if undetermined < 0.05 and progressive < 0.8:
                if tff >= 0.8 or bff >= 0.8:
                    # It's probably interlaced.
                    return True
    return False
示例#4
0
def detect_ffprobe(path):
    # IMPORTANT: jdiez, this doesn't work when the path has spaces in it
    # I tried wrapping {0} in quotes to no avail
    a = Invocation('ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout[0])
    if result["format"]["nb_streams"] == 1:
        return detect_stream(result["streams"][0])
    # Try to guess what it is from the streams inside
    # I've done a little more detection than we really need to, for things like subtitles
    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    for stream in result["streams"]:
        s = detect_stream(stream)
        t = s['type']
        if not s or not t:
            unknown_streams += 1
        else:
            if t.startswith('image'):
                image_streams += 1
            elif t == 'video':
                video_streams += 1
            elif t == 'audio':
                audio_streams += 1
            elif t == 'subtitle':
                subtitle_streams += 1
            elif t == 'font':
                font_streams += 1
            else:
                unknown_streams += 1
    if audio_streams == 1 and video_streams == 0:
        return {
            'type': 'audio',
            'extra': { 'has_audio': True, 'has_video': False },
            'flags': None
        }
    if video_streams > 0:
        return {
            'type': 'video',
            'extra': { 'has_audio': audio_streams > 0, 'has_video': True },
            'flags': {
                'autoplay': False,
                'loop': False,
                'mute': False,
            }
        }
    return None
示例#5
0
def detect_plaintext(path):
    a = Invocation('file -b -e elf -e tar -e compress -e cdf -e apptype -i {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None, None
    result = a.stdout[0]
    if result.startswith('text/x-') or result == 'text/plain':
        return result[:result.find(';')]
    return None, None
示例#6
0
    def _execute(self, command, ignoreNonZero = False):
        ext = extension(self.f.original)

        tlc = Invocation(command)(self.path, self.output, extension=ext)
        tlc.run(self.time if not self.ignore_limit else None)

        if tlc.exited and self.important:
            raise TimeoutException

        if tlc.returncode != 0 and self.important and not ignoreNonZero:
            raise ProcessingException
示例#7
0
    def _execute(self, command):
        ext = extension(self.f.original)

        tlc = Invocation(command)(self.path, self.output, extension=ext)
        tlc.run(self.time)

        if tlc.exited and self.important:
            raise TimeoutException

        if tlc.returncode != 0 and self.important:
            raise ProcessingException
示例#8
0
    def _execute(self, command):
        ext = extension(self.f.original)

        tlc = Invocation(command)(self.path, self.output, extension=ext)
        tlc.run(self.time)

        if tlc.exited and self.important:
            raise TimeoutException

        if tlc.returncode != 0 and self.important:
            raise ProcessingException
示例#9
0
    def _execute(self, command, ignoreNonZero=False):
        ext = extension(self.f.original)

        tlc = Invocation(command)(self.path, self.output, extension=ext)
        tlc.run(self.time if not self.ignore_limit else None)

        if tlc.exited and self.important:
            raise TimeoutException

        if tlc.returncode != 0 and self.important and not ignoreNonZero:
            raise ProcessingException
示例#10
0
文件: detect.py 项目: wub/MediaCrush
def detect_plaintext(path):
    a = Invocation('file -b -e elf -e tar -e compress -e cdf -e apptype -i {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout[0]
    if result.startswith('text/x-') or result == 'text/plain':
        return {
            'type': result[:result.find(';')],
            'metadata': None,
            'processor_state': None,
            'flags': None
        }
    return None
示例#11
0
def detect_plaintext(path):
    a = Invocation("file -b -e elf -e tar -e compress -e cdf -e apptype -i {0}")
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout
    if result.startswith("text/x-") or result == "text/plain":
        return {
            "type": result[: result.find(";")],
            "metadata": None,
            "processor_state": None,
            "flags": None,
        }
    return None
示例#12
0
def detect_plaintext(path):
    a = Invocation('file -b -e elf -e tar -e compress -e cdf -e apptype -i {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout[0]
    if result.startswith('text/x-') or result == 'text/plain':
        return {
            'type': result[:result.find(';')],
            'metadata': None,
            'processor_state': None,
            'flags': None
        }
    return None
示例#13
0
def detect_imagemagick(path):
    a = Invocation('identify -verbose {0}')
    a(path)
    a.run()
    try:
        result = a.stdout[0].split('\n')
        # Get mime type and dimensions
        mimetype = None
        metadata = None
        for line in result:
            line = line.lstrip(' ')
            if line.startswith('Mime type: '):
                mimetype = line[11:]
            match = re.search('(\d+)x(\d+)', line)
            if line.startswith('Geometry: '):
                metadata = {
                    'dimensions': {
                        'width': int(match.group(1)),
                        'height': int(match.group(2))
                    }
                }
        if mimetype in ['image/png', 'image/jpeg', 'image/svg+xml']:
            return {
                'type': mimetype,
                'metadata': metadata,
                'processor_state': None,
                'flags': None
            }
        # Check for other formats
        for line in result:
            line = line.lstrip(' ')
            if line == 'Format: XCF (GIMP image)':
                return {
                    'type': 'image/x-gimp-xcf',
                    'metadata': metadata,
                    'processor_state': None,
                    'flags': None
                }

        return {
            'type': 'image',
            'metadata': metadata,
            'processor_state': None,
            'flags': None
        }
    except Exception as e:
        print("ImageMagick failed detection", e)
        return None
示例#14
0
def detect_imagemagick(path):
    a = Invocation("identify -verbose {0}")
    a(path)
    a.run()
    try:
        result = a.stdout.split("\n")
        # Get mime type and dimensions
        mimetype = None
        metadata = None
        for line in result:
            line = line.lstrip(" ")
            if line.startswith("Mime type: "):
                mimetype = line[11:]
            match = re.search("(\d+)x(\d+)", line)
            if line.startswith("Geometry: "):
                metadata = {
                    "dimensions": {
                        "width": int(match.group(1)),
                        "height": int(match.group(2)),
                    }
                }
        if mimetype in ["image/png", "image/jpeg", "image/svg+xml"]:
            return {
                "type": mimetype,
                "metadata": metadata,
                "processor_state": None,
                "flags": None,
            }
        # Check for other formats
        for line in result:
            line = line.lstrip(" ")
            if line == "Format: XCF (GIMP image)":
                return {
                    "type": "image/x-gimp-xcf",
                    "metadata": metadata,
                    "processor_state": None,
                    "flags": None,
                }

        return {
            "type": "image",
            "metadata": metadata,
            "processor_state": None,
            "flags": None,
        }
    except:
        return None
示例#15
0
def detect_imagemagick(path):
    a = Invocation('identify -verbose {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout[0].split('\n')
    # Check for an actual mimetype first
    mimetype = None
    for line in result:
        line = line.lstrip(' ')
        if line.startswith('Mime type: '):
            mimetype = line[11:]
    if mimetype in ['image/png', 'image/jpeg']:
        return {
            'type': mimetype,
            'metadata': None,
            'processor_state': None,
            'flags': None
        }
    # Check for other formats
    for line in result:
        line = line.lstrip(' ')
        if line == 'Format: SVG (Scalable Vector Graphics)':
            return {
                'type': 'image/svg+xml',
                'metadata': None,
                'processor_state': None,
                'flags': None
            }
        if line == 'Format: XCF (GIMP image)':
            return {
                'type': 'image/x-gimp-xcf',
                'metadata': None,
                'processor_state': None,
                'flags': None
            }

    return {
        'type': 'image',
        'metadata': None,
        'processor_state': None,
        'flags': None
    }
示例#16
0
def detect_imagemagick(path):
    a = Invocation('identify -verbose {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = a.stdout[0].split('\n')
    # Check for an actual mimetype first
    mimetype = None
    for line in result:
        line = line.lstrip(' ')
        if line.startswith('Mime type: '):
            mimetype = line[11:]
    if mimetype in [ 'image/png', 'image/jpeg' ]:
        return {
            'type': mimetype,
            'metadata': None,
            'processor_state': None,
            'flags': None
        }
    # Check for other formats
    for line in result:
        line = line.lstrip(' ')
        if line == 'Format: SVG (Scalable Vector Graphics)':
            return {
                'type': 'image/svg+xml',
                'metadata': None,
                'processor_state': None,
                'flags': None
            }
        if line == 'Format: XCF (GIMP image)':
            return {
                'type': 'image/x-gimp-xcf',
                'metadata': None,
                'processor_state': None,
                'flags': None
            }

    return {
        'type': 'image',
        'metadata': None,
        'processor_state': None,
        'flags': None
    }
示例#17
0
def detect_imagemagick(path):
    a = Invocation('identify -verbose {0}')
    a(path)
    a.run()
    try:
        result = a.stdout[0].split('\n')
        # Get mime type and dimensions
        mimetype = None
        metadata = None
        for line in result:
            line = line.lstrip(' ')
            if line.startswith('Mime type: '):
                mimetype = line[11:]
            match = re.search('(\d+)x(\d+)', line)
            if line.startswith('Geometry: '):
                metadata = { 'dimensions': { 'width': int(match.group(1)), 'height': int(match.group(2)) } }
        if mimetype in [ 'image/png', 'image/jpeg', 'image/svg+xml' ]:
            return {
                'type': mimetype,
                'metadata': metadata,
                'processor_state': None,
                'flags': None
            }
        # Check for other formats
        for line in result:
            line = line.lstrip(' ')
            if line == 'Format: XCF (GIMP image)':
                return {
                    'type': 'image/x-gimp-xcf',
                    'metadata': metadata,
                    'processor_state': None,
                    'flags': None
                }

        return {
            'type': 'image',
            'metadata': metadata,
            'processor_state': None,
            'flags': None
        }
    except:
        return None
示例#18
0
 def sync(self):
     self._execute(copy)
     map_string = ''
     filter_string = 'scale=trunc(in_w/2)*2:trunc(in_h/2)*2'
     if self.processor_state['has_video']:
         self._execute("ffmpeg -y -i {0} -vframes 1 -map 0:v:0 {1}.jpg")
         map_string += ' -map 0:v:0'
     if self.processor_state['has_audio']:
         map_string += ' -map 0:a:0'
     if 'interlaced' in self.processor_state:
         print("WARNING: Detected interlacing on " + self.output)
         filter_string = 'yadif,' + filter_string
     self._execute(
         "ffmpeg -y -i {0} -vcodec libx264 -acodec libfdk_aac -movflags faststart -pix_fmt yuv420p -profile:v baseline -level 3.0 -preset slower -crf 18 -vf "
         + filter_string + map_string + " {1}.mp4")
     skip_webm = False
     for s in self.processor_state['streams']:
         if 'info' in s:
             if 'video_codec' in s['info'] and s['info'][
                     'video_codec'] == 'vp8':
                 skip_webm = True
     if not skip_webm:
         self._execute(
             "ffmpeg -y -i {0} -c:v libvpx -c:a libvorbis -pix_fmt yuv420p -quality good -b:v 5M -crf 5 -vf "
             + filter_string + map_string + " {1}.webm")
     # Extract extra streams if present
     fonts = []
     extract_fonts = False
     if 'has_fonts' in self.processor_state and 'has_subtitles' in self.processor_state:
         if self.processor_state['has_fonts'] or self.processor_state[
                 'has_subtitles']:
             for stream in self.processor_state['streams']:
                 if stream['type'] == 'font':
                     ext = _extension(stream["info"])
                     if ext in ['ttf', 'otf']:
                         # Note that ffmpeg returns a nonzero exit code when dumping attachments because there's technically no output file
                         # -dump_attachment is a mechanism completely removed from the rest of the ffmpeg workflow
                         self._execute(
                             "ffmpeg -y -dump_attachment:" +
                             str(stream["index"]) + ' {1}_attachment_' +
                             str(len(fonts)) + '.' + ext + ' -i {0}',
                             ignoreNonZero=True)
                         fonts.append(stream)
                 elif stream['type'] == 'subtitle' and 'info' in stream:
                     extension = None
                     if stream['info']['codec_name'] == 'ssa':
                         extension = '.ass'
                         extract_fonts = True
                     elif stream['info']['codec_name'] == 'srt':
                         extension = '.srt'
                     elif stream['info']['codec_name'] == 'vtt':
                         extension = '.vtt'
                     if extension != None:
                         self._execute("ffmpeg -y -i {0} -map 0:s:0 {1}" +
                                       extension)
                         if extension == '.srt':
                             # convert to vtt
                             vtt = convert_to_vtt(
                                 os.path.join(_cfg("storage_folder"),
                                              '%s.srt' % self.f.hash))
                             with open(
                                     os.path.join(_cfg("storage_folder"),
                                                  '%s.vtt' % self.f.hash),
                                     'w') as f:
                                 f.write(vtt)
                             os.remove(
                                 os.path.join(_cfg("storage_folder"),
                                              '%s.srt' % self.f.hash))
         if extract_fonts:
             # Examine font files and construct some CSS to import them
             css = ''
             i = 0
             for font in fonts:
                 ext = _extension(font['info'])
                 if not ext in ['ttf', 'otf']:
                     continue
                 command = Invocation('otfinfo --info {0}')
                 command(
                     os.path.join(
                         _cfg("storage_folder"), '%s_attachment_%s.%s' %
                         (self.f.hash, i, _extension(font['info']))))
                 command.run()
                 output = command.stdout[0].split('\n')
                 family = None
                 subfamily = None
                 for line in output:
                     if line.startswith('Family:'):
                         family = line[7:].strip(' \t')
                     if line.startswith('Subfamily:'):
                         subfamily = line[10:].strip(' \t')
                 css += '@font-face{font-family: "%s";' % family
                 css += 'src:url("/%s_attachment_%s.%s");' % (
                     self.f.hash, i, _extension(font['info']))
                 if subfamily == 'SemiBold':
                     css += 'font-weight: 600;'
                 elif subfamily == 'Bold':
                     css += 'font-weight: bold;'
                 elif subfamily == 'Italic':
                     css += 'font-style: italic;'
                 css += '}'
                 i += 1
             css_file = open(
                 os.path.join(_cfg("storage_folder"),
                              '%s_fonts.css' % self.f.hash), 'w')
             css_file.write(css)
             css_file.close()
示例#19
0
 def sync(self):
     self._execute(copy)
     map_string = ''
     filter_string = 'scale=trunc(in_w/2)*2:trunc(in_h/2)*2'
     if self.processor_state['has_video']:
         self._execute("ffmpeg -y -i {0} -vframes 1 -map 0:v:0 {1}.jpg")
         map_string += ' -map 0:v:0'
     if self.processor_state['has_audio']:
         map_string += ' -map 0:a:0'
     if 'interlaced' in self.processor_state:
         print("WARNING: Detected interlacing on " + self.output)
         filter_string = 'yadif,' + filter_string
     self._execute("ffmpeg -y -i {0} -vcodec libx264 -acodec libfdk_aac -pix_fmt yuv420p -profile:v baseline -preset slower -crf 18 -vf " + filter_string + map_string  + " {1}.mp4")
     skip_webm = False
     for s in self.processor_state['streams']:
         if 'info' in s:
             if 'video_codec' in s['info'] and s['info']['video_codec'] == 'vp8':
                 skip_webm = True
     if not skip_webm:
         self._execute("ffmpeg -y -i {0} -c:v libvpx -c:a libvorbis -pix_fmt yuv420p -quality good -b:v 5M -crf 5 -vf " + filter_string + map_string + " {1}.webm")
     # Extract extra streams if present
     fonts = []
     extract_fonts = False
     if 'has_fonts' in self.processor_state and 'has_subtitles' in self.processor_state:
         if self.processor_state['has_fonts'] or self.processor_state['has_subtitles']:
             for stream in self.processor_state['streams']:
                 if stream['type'] == 'font':
                     ext = _extension(stream["info"])
                     if ext in ['ttf', 'otf']:
                         # Note that ffmpeg returns a nonzero exit code when dumping attachments because there's technically no output file
                         # -dump_attachment is a mechanism completely removed from the rest of the ffmpeg workflow
                         self._execute("ffmpeg -y -dump_attachment:" + str(stream["index"]) + ' {1}_attachment_' + str(len(fonts)) + '.' + ext + ' -i {0}', ignoreNonZero=True)
                         fonts.append(stream)
                 elif stream['type'] == 'subtitle' and 'info' in stream:
                     extension = None
                     if stream['info']['codec_name'] == 'ssa':
                         extension = '.ass'
                         extract_fonts = True
                     elif stream['info']['codec_name'] == 'srt':
                         extension = '.srt'
                     elif stream['info']['codec_name'] == 'vtt':
                         extension = '.vtt'
                     if extension != None:
                         self._execute("ffmpeg -y -i {0} -map 0:s:0 {1}" + extension)
                         if extension == '.srt':
                             # convert to vtt
                             vtt = convert_to_vtt(os.path.join(_cfg("storage_folder"), '%s.srt' % self.f.hash))
                             with open(os.path.join(_cfg("storage_folder"), '%s.vtt' % self.f.hash), 'w') as f:
                                 f.write(vtt)
                             os.remove(os.path.join(_cfg("storage_folder"), '%s.srt' % self.f.hash))
         if extract_fonts:
             # Examine font files and construct some CSS to import them
             css = ''
             i = 0
             for font in fonts:
                 ext = _extension(font['info'])
                 if not ext in ['ttf', 'otf']:
                     continue
                 command = Invocation('otfinfo --info {0}')
                 command(os.path.join(_cfg("storage_folder"), '%s_attachment_%s.%s' % (self.f.hash, i, _extension(font['info']))))
                 command.run()
                 output = command.stdout[0].split('\n')
                 family = None
                 subfamily = None
                 for line in output:
                     if line.startswith('Family:'):
                         family = line[7:].strip(' \t')
                     if line.startswith('Subfamily:'):
                         subfamily = line[10:].strip(' \t')
                 css += '@font-face{font-family: "%s";' % family
                 css += 'src:url("/%s_attachment_%s.%s");' % (self.f.hash, i, _extension(font['info']))
                 if subfamily == 'SemiBold':
                     css += 'font-weight: 600;'
                 elif subfamily == 'Bold':
                     css += 'font-weight: bold;'
                 elif subfamily == 'Italic':
                     css += 'font-style: italic;'
                 css += '}'
                 i += 1
             css_file = open(os.path.join(_cfg("storage_folder"), '%s_fonts.css' % self.f.hash), 'w')
             css_file.write(css)
             css_file.close()
示例#20
0
文件: detect.py 项目: imgrush/Imgrush
def detect_ffprobe(path):
    a = Invocation(
        'ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}'
    )
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout[0])

    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    metadata = dict()
    state = dict()
    flags = dict()
    state['streams'] = list()
    index = 0

    for stream in result["streams"]:
        s = detect_stream(stream)
        if s == None:
            continue
        # Set up some metadata
        if s['metadata'] != None:
            if 'duration' in s['metadata']:
                metadata['duration'] = s['metadata']['duration']
            if 'dimensions' in s['metadata']:
                metadata['dimensions'] = s['metadata']['dimensions']
        t = s['type']
        if not s or not t:
            unknown_streams += 1
        else:
            state['streams'].append({
                'type': t,
                'info': s['processor_state'],
                'index': index
            })
            if t.startswith('image'):
                image_streams += 1
            elif t == 'video':
                video_streams += 1
                flags = s['flags']
            elif t == 'audio':
                audio_streams += 1
            elif t == 'subtitle':
                subtitle_streams += 1
            elif t == 'font':
                font_streams += 1
            else:
                unknown_streams += 1
        index += 1
    metadata = ffprobe_addExtraMetadata(metadata, result)
    if audio_streams == 1 and video_streams == 0:
        metadata['has_audio'] = True
        metadata['has_video'] = False
        state['has_audio'] = True
        state['has_video'] = False
        return {
            'type': 'audio',
            'processor_state': state,
            'metadata': metadata,
            'flags': None
        }
    if video_streams > 0:
        metadata['has_audio'] = audio_streams > 0
        metadata['has_video'] = True
        metadata['has_subtitles'] = subtitle_streams > 0
        state['has_audio'] = audio_streams > 0
        state['has_video'] = True
        state['has_fonts'] = font_streams > 0
        state['has_subtitles'] = subtitle_streams > 0
        if subtitle_streams > 0:
            metadata = addSubtitleInfo(metadata, state)
        if detect_interlacing(path):
            state['interlaced'] = True
        return {
            'type': 'video',
            'processor_state': state,
            'metadata': metadata,
            'flags': flags
        }
    return None
示例#21
0
def detect_ffprobe(path):
    a = Invocation('ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout[0])

    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    metadata = dict()
    state = dict()
    flags = dict()
    state['streams'] = list()
    index = 0

    for stream in result["streams"]:
        s = detect_stream(stream)
        # Set up some metadata
        if s['metadata'] != None:
            if 'duration' in s['metadata']:
                metadata['duration'] = s['metadata']['duration']
            if 'dimensions' in s['metadata']:
                metadata['dimensions'] = s['metadata']['dimensions']
        t = s['type']
        if not s or not t:
            unknown_streams += 1
        else:
            state['streams'].append({
                'type': t,
                'info': s['processor_state'],
                'index': index
            })
            if t.startswith('image'):
                image_streams += 1
            elif t == 'video':
                video_streams += 1
                flags = s['flags']
            elif t == 'audio':
                audio_streams += 1
            elif t == 'subtitle':
                subtitle_streams += 1
            elif t == 'font':
                font_streams += 1
            else:
                unknown_streams += 1
        index += 1
    metadata = ffprobe_addExtraMetadata(metadata, result)
    if audio_streams == 1 and video_streams == 0:
        metadata['has_audio'] = True
        metadata['has_video'] = False
        state['has_audio'] = True
        state['has_video'] = False
        return {
            'type': 'audio',
            'processor_state': state,
            'metadata': metadata,
            'flags': None
        }
    if video_streams > 0:
        metadata['has_audio'] = audio_streams > 0
        metadata['has_video'] = True
        metadata['has_subtitles'] = subtitle_streams > 0
        state['has_audio'] = audio_streams > 0
        state['has_video'] = True
        state['has_fonts'] = font_streams > 0
        state['has_subtitles'] = subtitle_streams > 0
        if subtitle_streams > 0:
            metadata = addSubtitleInfo(metadata, state)
        if detect_interlacing(path):
            state['interlaced'] = True
        return {
            'type': 'video',
            'processor_state': state,
            'metadata': metadata,
            'flags': flags
        }
    return None
示例#22
0
 def sync(self):
     self._execute(copy)
     map_string = ""
     filter_string = "scale=trunc(in_w/2)*2:trunc(in_h/2)*2"
     if self.processor_state["has_video"]:
         self._execute("ffmpeg -y -i {0} -vframes 1 -map 0:v:0 {1}.jpg")
         map_string += " -map 0:v:0"
     if self.processor_state["has_audio"]:
         map_string += " -map 0:a:0"
     if "interlaced" in self.processor_state:
         print(("WARNING: Detected interlacing on " + self.output))
         filter_string = "yadif," + filter_string
     self._execute(
         "ffmpeg -y -i {0} -vcodec libx264 -acodec libfdk_aac -movflags faststart -pix_fmt yuv420p -profile:v baseline -level 3.0 -preset slower -crf 18 -vf "
         + filter_string
         + map_string
         + " {1}.mp4"
     )
     skip_webm = False
     for s in self.processor_state["streams"]:
         if "info" in s:
             if "video_codec" in s["info"] and s["info"]["video_codec"] == "vp8":
                 skip_webm = True
     if not skip_webm:
         self._execute(
             "ffmpeg -y -i {0} -c:v libvpx -c:a libvorbis -q:a 5 -pix_fmt yuv420p -quality good -b:v 5M -crf 5 -vf "
             + filter_string
             + map_string
             + " {1}.webm"
         )
     # Extract extra streams if present
     fonts = []
     extract_fonts = False
     if (
         "has_fonts" in self.processor_state
         and "has_subtitles" in self.processor_state
     ):
         if (
             self.processor_state["has_fonts"]
             or self.processor_state["has_subtitles"]
         ):
             for stream in self.processor_state["streams"]:
                 if stream["type"] == "font":
                     ext = _extension(stream["info"])
                     if ext in ["ttf", "otf"]:
                         # Note that ffmpeg returns a nonzero exit code when dumping attachments because there's technically no output file
                         # -dump_attachment is a mechanism completely removed from the rest of the ffmpeg workflow
                         self._execute(
                             "ffmpeg -y -dump_attachment:"
                             + str(stream["index"])
                             + " {1}_attachment_"
                             + str(len(fonts))
                             + "."
                             + ext
                             + " -i {0}",
                             ignoreNonZero=True,
                         )
                         fonts.append(stream)
                 elif stream["type"] == "subtitle" and "info" in stream:
                     extension = None
                     if stream["info"]["codec_name"] == "ssa":
                         extension = ".ass"
                         extract_fonts = True
                     elif stream["info"]["codec_name"] == "srt":
                         extension = ".srt"
                     elif stream["info"]["codec_name"] == "vtt":
                         extension = ".vtt"
                     if extension != None:
                         self._execute("ffmpeg -y -i {0} -map 0:s:0 {1}" + extension)
                         if extension == ".srt":
                             # convert to vtt
                             vtt = convert_to_vtt(
                                 os.path.join(
                                     _cfg("storage_folder"), "%s.srt" % self.f.hash
                                 )
                             )
                             with open(
                                 os.path.join(
                                     _cfg("storage_folder"), "%s.vtt" % self.f.hash
                                 ),
                                 "w",
                             ) as f:
                                 f.write(vtt)
                             os.remove(
                                 os.path.join(
                                     _cfg("storage_folder"), "%s.srt" % self.f.hash
                                 )
                             )
         if extract_fonts:
             # Examine font files and construct some CSS to import them
             css = ""
             i = 0
             for font in fonts:
                 ext = _extension(font["info"])
                 if not ext in ["ttf", "otf"]:
                     continue
                 command = Invocation("otfinfo --info {0}")
                 command(
                     os.path.join(
                         _cfg("storage_folder"),
                         "%s_attachment_%s.%s"
                         % (self.f.hash, i, _extension(font["info"])),
                     )
                 )
                 command.run()
                 output = command.stdout[0].split("\n")
                 family = None
                 subfamily = None
                 for line in output:
                     if line.startswith("Family:"):
                         family = line[7:].strip(" \t")
                     if line.startswith("Subfamily:"):
                         subfamily = line[10:].strip(" \t")
                 css += '@font-face{font-family: "%s";' % family
                 css += 'src:url("/%s_attachment_%s.%s");' % (
                     self.f.hash,
                     i,
                     _extension(font["info"]),
                 )
                 if subfamily == "SemiBold":
                     css += "font-weight: 600;"
                 elif subfamily == "Bold":
                     css += "font-weight: bold;"
                 elif subfamily == "Italic":
                     css += "font-style: italic;"
                 css += "}"
                 i += 1
             css_file = open(
                 os.path.join(_cfg("storage_folder"), "%s_fonts.css" % self.f.hash),
                 "w",
             )
             css_file.write(css)
             css_file.close()
示例#23
0
def detect_ffprobe(path):
    a = Invocation(
        'ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}'
    )
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout[0])
    if result["format"]["nb_streams"] == 1:
        detected = detect_stream(result["streams"][0])
        if detected != None:
            detected['metadata'] = ffprobe_addExtraMetadata(
                detected['metadata'], result)
        return detected
    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    metadata = dict()

    for stream in result["streams"]:
        s = detect_stream(stream)
        # Set up some metadata
        if s['metadata'] != None:
            if 'duration' in s['metadata']:
                metadata['duration'] = s['metadata']['duration']
            if 'dimensions' in s['metadata']:
                metadata['dimensions'] = s['metadata']['dimensions']
        t = s['type']
        if not s or not t:
            unknown_streams += 1
        else:
            if t.startswith('image'):
                image_streams += 1
            elif t == 'video':
                video_streams += 1
            elif t == 'audio':
                audio_streams += 1
            elif t == 'subtitle':
                subtitle_streams += 1
            elif t == 'font':
                font_streams += 1
            else:
                unknown_streams += 1
    metadata = ffprobe_addExtraMetadata(metadata, result)
    if audio_streams == 1 and video_streams == 0:
        metadata['has_audio'] = True
        metadata['has_video'] = False
        return {
            'type': 'audio',
            'processor_state': {
                'has_audio': True,
                'has_video': False
            },
            'metadata': metadata,
            'flags': None
        }
    if video_streams > 0:
        metadata['has_audio'] = audio_streams > 0
        metadata['has_video'] = True
        return {
            'type': 'video',
            'processor_state': {
                'has_audio': audio_streams > 0,
                'has_video': True
            },
            'metadata': metadata,
            'flags': {
                'autoplay': False,
                'loop': False,
                'mute': False,
            }
        }
    return None
示例#24
0
def detect_ffprobe(path):
    a = Invocation('ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}')
    a(path)
    a.run()
    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout[0])
    if result["format"]["nb_streams"] == 1:
        detected = detect_stream(result["streams"][0])
        if detected != None:
            detected['metadata'] = ffprobe_addExtraMetadata(detected['metadata'], result)
        return detected
    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    metadata = dict()

    for stream in result["streams"]:
        s = detect_stream(stream)
        # Set up some metadata
        if s['metadata'] != None:
            if 'duration' in s['metadata']:
                metadata['duration'] = s['metadata']['duration']
            if 'dimensions' in s['metadata']:
                metadata['dimensions'] = s['metadata']['dimensions']
        t = s['type']
        if not s or not t:
            unknown_streams += 1
        else:
            if t.startswith('image'):
                image_streams += 1
            elif t == 'video':
                video_streams += 1
            elif t == 'audio':
                audio_streams += 1
            elif t == 'subtitle':
                subtitle_streams += 1
            elif t == 'font':
                font_streams += 1
            else:
                unknown_streams += 1
    metadata = ffprobe_addExtraMetadata(metadata, result)
    if audio_streams == 1 and video_streams == 0:
        metadata['has_audio'] = True
        metadata['has_video'] = False
        return {
            'type': 'audio',
            'processor_state': { 'has_audio': True, 'has_video': False },
            'metadata': metadata,
            'flags': None
        }
    if video_streams > 0:
        metadata['has_audio'] = audio_streams > 0
        metadata['has_video'] = True
        return {
            'type': 'video',
            'processor_state': { 'has_audio': audio_streams > 0, 'has_video': True },
            'metadata': metadata,
            'flags': {
                'autoplay': False,
                'loop': False,
                'mute': False,
            }
        }
    return None
示例#25
0
def detect_ffprobe(path):
    a = Invocation(
        "ffprobe -print_format json -loglevel quiet -show_format -show_streams {0}"
    )
    a(path)
    a.run()

    if a.returncode or a.exited:
        return None
    result = json.loads(a.stdout)

    audio_streams = 0
    video_streams = 0
    image_streams = 0
    subtitle_streams = 0
    font_streams = 0
    # We shouldn't penalize people for unknown streams, I just figured we could make a note of it
    unknown_streams = 0

    metadata = dict()
    state = dict()
    flags = dict()
    state["streams"] = list()
    index = 0

    for stream in result["streams"]:
        s = detect_stream(stream)
        if s == None:
            continue
        # Set up some metadata
        if s["metadata"] != None:
            if "duration" in s["metadata"]:
                metadata["duration"] = s["metadata"]["duration"]
            if "dimensions" in s["metadata"]:
                metadata["dimensions"] = s["metadata"]["dimensions"]
        t = s["type"]
        if not s or not t:
            unknown_streams += 1
        else:
            state["streams"].append(
                {"type": t, "info": s["processor_state"], "index": index}
            )
            if t.startswith("image"):
                image_streams += 1
            elif t == "video":
                video_streams += 1
                flags = s["flags"]
            elif t == "audio":
                audio_streams += 1
            elif t == "subtitle":
                subtitle_streams += 1
            elif t == "font":
                font_streams += 1
            else:
                unknown_streams += 1
        index += 1
    metadata = ffprobe_addExtraMetadata(metadata, result)
    if audio_streams == 1 and video_streams == 0:
        metadata["has_audio"] = True
        metadata["has_video"] = False
        state["has_audio"] = True
        state["has_video"] = False
        return {
            "type": "audio",
            "processor_state": state,
            "metadata": metadata,
            "flags": None,
        }
    if video_streams > 0:
        metadata["has_audio"] = audio_streams > 0
        metadata["has_video"] = True
        metadata["has_subtitles"] = subtitle_streams > 0
        state["has_audio"] = audio_streams > 0
        state["has_video"] = True
        state["has_fonts"] = font_streams > 0
        state["has_subtitles"] = subtitle_streams > 0
        if subtitle_streams > 0:
            metadata = addSubtitleInfo(metadata, state)
        if detect_interlacing(path):
            state["interlaced"] = True
        return {
            "type": "video",
            "processor_state": state,
            "metadata": metadata,
            "flags": flags,
        }
    return None