Example #1
0
def get_media_info(filepath):
    """Takes a file path and returns a dict of information about
    this media file that it extracted from ffmpeg -i.

    :param filepath: absolute path to the media file in question

    :returns: dict of media info possibly containing: height, width,
    container, audio_codec, video_codec
    """

    ffmpeg_bin = utils.get_ffmpeg_executable_path()
    retcode, stdout, stderr = util.call_command(ffmpeg_bin,
                                                "-i",
                                                "%s" % filepath,
                                                return_everything=True)

    if stdout:
        output = stdout
    else:
        output = stderr

    # logging.info("get_media_info: %s %s", filepath, output)
    ast = parse_ffmpeg_output(output.splitlines())

    return extract_info(ast)
Example #2
0
def convert(args):
    cm = conversions.ConverterManager()
    cm.load_converters(resources.path('conversions/*.conv'))

    if len(args) < 2:
        print USAGE
        print "Available targets:"
        for section, converters in cm.get_converters():
            print "  %s" % section
            for mem in converters:
                print "    %s - %s" % (mem.identifier, mem.name)
        return

    target = args[0]
    infiles = args[1:]

    try:
        converter_info = cm.lookup_converter(target)
    except KeyError:
        print "That target doesn't exist."
        return

    for mem in infiles:
        input_file = os.path.abspath(mem)
        if not os.path.exists(input_file):
            print "File %s does not exist.  Skipping." % input_file
            continue
        final_path, temp_path = conversions.build_output_paths(
            FakeInfo(input_file), os.getcwd(), converter_info)

        media_info = conversions.get_media_info(input_file)

        params = conversions.build_parameters(
            mem, temp_path, converter_info, media_info)
        if converter_info.executable == "ffmpeg":
            cmd = utils.get_ffmpeg_executable_path()
            params = utils.customize_ffmpeg_parameters(params)
        else:
            cmd = utils.get_ffmpeg2theora_executable_path()
            params = utils.customize_ffmpeg2theora_parameters(params)

        params.insert(0, cmd)

        print "\nCONVERTING %s -> %s\n" % (mem, final_path)
        print "ffmpeg command line:"
        print " ".join(params)
        print "\n"

        retcall = subprocess.call(params)
        if retcall == 0:
            shutil.move(temp_path, final_path)
            print "Success!  New file at %s." % final_path
Example #3
0
def convert(args):
    cm = conversions.ConverterManager()
    cm.load_converters(resources.path('conversions/*.conv'))

    if len(args) < 2:
        print USAGE
        print "Available targets:"
        for section, converters in cm.get_converters():
            print "  %s" % section
            for mem in converters:
                print "    %s - %s" % (mem.identifier, mem.name)
        return

    target = args[0]
    infiles = args[1:]

    try:
        converter_info = cm.lookup_converter(target)
    except KeyError:
        print "That target doesn't exist."
        return

    for mem in infiles:
        input_file = os.path.abspath(mem)
        if not os.path.exists(input_file):
            print "File %s does not exist.  Skipping." % input_file
            continue
        final_path, temp_path = conversions.build_output_paths(
            FakeInfo(input_file), os.getcwd(), converter_info)

        media_info = conversions.get_media_info(input_file)

        params = conversions.build_parameters(mem, temp_path, converter_info,
                                              media_info)
        if converter_info.executable == "ffmpeg":
            cmd = utils.get_ffmpeg_executable_path()
            params = utils.customize_ffmpeg_parameters(params)
        else:
            cmd = utils.get_ffmpeg2theora_executable_path()
            params = utils.customize_ffmpeg2theora_parameters(params)

        params.insert(0, cmd)

        print "\nCONVERTING %s -> %s\n" % (mem, final_path)
        print "ffmpeg command line:"
        print " ".join(params)
        print "\n"

        retcall = subprocess.call(params)
        if retcall == 0:
            shutil.move(temp_path, final_path)
            print "Success!  New file at %s." % final_path
Example #4
0
def get_media_info(filepath):
    """Takes a file path and returns a dict of information about
    this media file that it extracted from ffmpeg -i.

    :param filepath: absolute path to the media file in question

    :returns: dict of media info possibly containing: height, width,
    container, audio_codec, video_codec
    """

    ffmpeg_bin = utils.get_ffmpeg_executable_path()
    retcode, stdout, stderr = util.call_command(ffmpeg_bin, "-i", "%s" % filepath, return_everything=True)

    if stdout:
        output = stdout
    else:
        output = stderr

    # logging.info("get_media_info: %s %s", filepath, output)
    ast = parse_ffmpeg_output(output.splitlines())

    return extract_info(ast)
Example #5
0
 def get_executable(self):
     return utils.get_ffmpeg_executable_path()
Example #6
0
    def transcode(self):
        rc = True
        try:
            ffmpeg_exe = get_ffmpeg_executable_path()
            kwargs = {
                "stdin": open(os.devnull, 'rb'),
                "stdout": subprocess.PIPE,
                "stderr": open(os.devnull, 'wb'),
                "startupinfo": util.no_console_startupinfo()
            }
            if os.name != "nt":
                kwargs["close_fds"] = True
            args = [ffmpeg_exe, "-i", self.media_file]
            if self.time_offset:
                logging.debug('transcode: start job @ %d' % self.time_offset)
                args += TranscodeObject.time_offset_args + [
                    str(self.time_offset)
                ]
            video_needs_trancode = False
            if self.has_video:
                logging.debug('Video codec: %s', self.video_codec)
                logging.debug('Video size: %s', self.video_size)
                if video_can_copy(self.video_codec, self.video_size):
                    args += get_transcode_video_copy_options()
                else:
                    args += get_transcode_video_options()
                    video_needs_transcode = True
            if self.has_audio:
                logging.debug('Audio codec: %s', self.audio_codec)
                logging.debug('Audio sample rate: %s', self.audio_sample_rate)
                if (valid_av_combo(self.video_codec, self.audio_codec)
                        and audio_can_copy(self.audio_codec,
                                           self.audio_sample_rate)):
                    args += get_transcode_audio_copy_options()
                else:
                    args += get_transcode_audio_options()
            else:
                raise ValueError('no video or audio stream present')

            args += TranscodeObject.output_args
            logging.debug('Running command %s' % ' '.join(args))
            self.ffmpeg_handle = subprocess.Popen(args, **kwargs)

            segmenter_exe = get_segmenter_executable_path()
            args = [segmenter_exe]
            address, port = self.sink.server_address
            args += TranscodeObject.segmenter_args + [str(port)]
            kwargs = {
                "stdout": open(os.devnull, 'rb'),
                "stdin": self.ffmpeg_handle.stdout,
                "stderr": open(os.devnull, 'wb'),
                "startupinfo": util.no_console_startupinfo()
            }
            # XXX Can't use this - need to pass on the child fds
            #if os.name != "nt":
            #    kwargs["close_fds"] = True

            logging.debug('Running command %s' % ' '.join(args))
            self.segmenter_handle = subprocess.Popen(args, **kwargs)

            self.sink_thread = threading.Thread(target=thread_body,
                                                args=[self.segmenter_consumer],
                                                name="Segmenter Consumer")
            self.sink_thread.daemon = True
            self.sink_thread.start()

        except StandardError:
            (typ, value, tb) = sys.exc_info()
            logging.error('ERROR: %s %s' % (str(typ), str(value)))
            rc = False
        self.transcode_gate.set()
        return rc
Example #7
0
def needs_transcode(media_file):
    """needs_transcode()

    Returns (False, None) if no need to transcode.
    Returns (True, info) if there is a need to transcode.

    where info is

    (duration, has_audio, has_video)

    The duration is transmitted for transcoding purposes because we need to
    build a m3u8 playlist and what we get out of the Miro database may be 
    unreliable (does not exist).

    May throw exception if ffmpeg not found.  Remember to catch."""
    ffmpeg_exe = get_ffmpeg_executable_path()
    kwargs = {
        "stdout": subprocess.PIPE,
        "stderr": subprocess.PIPE,
        "stdin": subprocess.PIPE,
        "startupinfo": util.no_console_startupinfo()
    }
    if os.name != "nt":
        kwargs["close_fds"] = True
    args = [ffmpeg_exe, "-i", media_file]
    handle = subprocess.Popen(args, **kwargs)
    # XXX unbounded read here but should be okay, ffmpeg output is finite.
    # note that we need to read from stderr, since that's what ffmpeg spits
    # out.
    text = handle.stderr.read()
    # Initial determination based on the file type - need to drill down
    # to see if the resolution, etc are within parameters.
    if container_regex.search(text):
        transcode = False
    else:
        transcode = True
    # "    Duration: XX:XX:XX.XX, ..."
    match = duration_regex.search(text)
    start, end = match.span()
    duration_start = text[end:]
    duration = duration_start[:duration_start.index(',')]
    # Convert to seconds.  We can't handle fractions of a second so
    # skip over those bits.
    hours, minutes, seconds = duration.split(':')
    # Strip the fractional seconds.  Always round up, then we won't miss
    # any data.
    seconds = int(float(seconds) + 0.5)
    seconds += int(minutes) * 60
    seconds += int(hours) * 3600
    has_audio = has_audio_regex.search(text)
    has_video = has_video_regex.search(text)
    vcodec = acodec = size = sample_rate = None
    vcopy = acopy = False
    if has_video:
        vcodec, size = get_video_parameters(has_video)
        vcopy = video_can_copy(vcodec, size)
        if not vcopy:
            transcode = False
    if has_audio:
        acodec, sample_rate = get_audio_parameters(has_audio)
        acopy = audio_can_copy(acodec, sample_rate)
        if not acopy:
            transcode = False
    return (transcode, (seconds, has_audio, acodec, sample_rate, has_video,
                        vcodec, size))
Example #8
0
    def transcode(self):
        rc = True
        try:
            ffmpeg_exe = get_ffmpeg_executable_path()
            kwargs = {
                "stdin": open(os.devnull, "rb"),
                "stdout": subprocess.PIPE,
                "stderr": open(os.devnull, "wb"),
                "startupinfo": util.no_console_startupinfo(),
            }
            if os.name != "nt":
                kwargs["close_fds"] = True
            args = [ffmpeg_exe, "-i", self.media_file]
            if self.time_offset:
                logging.debug("transcode: start job @ %d" % self.time_offset)
                args += TranscodeObject.time_offset_args + [str(self.time_offset)]
            video_needs_trancode = False
            if self.has_video:
                logging.debug("Video codec: %s", self.video_codec)
                logging.debug("Video size: %s", self.video_size)
                if video_can_copy(self.video_codec, self.video_size):
                    args += get_transcode_video_copy_options()
                else:
                    args += get_transcode_video_options()
                    video_needs_transcode = True
            if self.has_audio:
                logging.debug("Audio codec: %s", self.audio_codec)
                logging.debug("Audio sample rate: %s", self.audio_sample_rate)
                if valid_av_combo(self.video_codec, self.audio_codec) and audio_can_copy(
                    self.audio_codec, self.audio_sample_rate
                ):
                    args += get_transcode_audio_copy_options()
                else:
                    args += get_transcode_audio_options()
            else:
                raise ValueError("no video or audio stream present")

            args += TranscodeObject.output_args
            logging.debug("Running command %s" % " ".join(args))
            self.ffmpeg_handle = subprocess.Popen(args, **kwargs)

            segmenter_exe = get_segmenter_executable_path()
            args = [segmenter_exe]
            address, port = self.sink.server_address
            args += TranscodeObject.segmenter_args + [str(port)]
            kwargs = {
                "stdout": open(os.devnull, "rb"),
                "stdin": self.ffmpeg_handle.stdout,
                "stderr": open(os.devnull, "wb"),
                "startupinfo": util.no_console_startupinfo(),
            }
            # XXX Can't use this - need to pass on the child fds
            # if os.name != "nt":
            #    kwargs["close_fds"] = True

            logging.debug("Running command %s" % " ".join(args))
            self.segmenter_handle = subprocess.Popen(args, **kwargs)

            self.sink_thread = threading.Thread(
                target=thread_body, args=[self.segmenter_consumer], name="Segmenter Consumer"
            )
            self.sink_thread.daemon = True
            self.sink_thread.start()

        except StandardError:
            (typ, value, tb) = sys.exc_info()
            logging.error("ERROR: %s %s" % (str(typ), str(value)))
            rc = False
        self.transcode_gate.set()
        return rc
Example #9
0
def needs_transcode(media_file):
    """needs_transcode()

    Returns (False, None) if no need to transcode.
    Returns (True, info) if there is a need to transcode.

    where info is

    (duration, has_audio, has_video)

    The duration is transmitted for transcoding purposes because we need to
    build a m3u8 playlist and what we get out of the Miro database may be 
    unreliable (does not exist).

    May throw exception if ffmpeg not found.  Remember to catch."""
    ffmpeg_exe = get_ffmpeg_executable_path()
    kwargs = {
        "stdout": subprocess.PIPE,
        "stderr": subprocess.PIPE,
        "stdin": subprocess.PIPE,
        "startupinfo": util.no_console_startupinfo(),
    }
    if os.name != "nt":
        kwargs["close_fds"] = True
    args = [ffmpeg_exe, "-i", media_file]
    handle = subprocess.Popen(args, **kwargs)
    # XXX unbounded read here but should be okay, ffmpeg output is finite.
    # note that we need to read from stderr, since that's what ffmpeg spits
    # out.
    text = handle.stderr.read()
    # Initial determination based on the file type - need to drill down
    # to see if the resolution, etc are within parameters.
    if container_regex.search(text):
        transcode = False
    else:
        transcode = True
    # "    Duration: XX:XX:XX.XX, ..."
    match = duration_regex.search(text)
    start, end = match.span()
    duration_start = text[end:]
    duration = duration_start[: duration_start.index(",")]
    # Convert to seconds.  We can't handle fractions of a second so
    # skip over those bits.
    hours, minutes, seconds = duration.split(":")
    # Strip the fractional seconds.  Always round up, then we won't miss
    # any data.
    seconds = int(float(seconds) + 0.5)
    seconds += int(minutes) * 60
    seconds += int(hours) * 3600
    has_audio = has_audio_regex.search(text)
    has_video = has_video_regex.search(text)
    vcodec = acodec = size = sample_rate = None
    vcopy = acopy = False
    if has_video:
        vcodec, size = get_video_parameters(has_video)
        vcopy = video_can_copy(vcodec, size)
        if not vcopy:
            transcode = False
    if has_audio:
        acodec, sample_rate = get_audio_parameters(has_audio)
        acopy = audio_can_copy(acodec, sample_rate)
        if not acopy:
            transcode = False
    return (transcode, (seconds, has_audio, acodec, sample_rate, has_video, vcodec, size))
Example #10
0
 def get_executable(self):
     return utils.get_ffmpeg_executable_path()