Esempio n. 1
0
def open_stream(stream):
    """Opens a stream and reads 8192 bytes from it.

    This is useful to check if a stream actually has data
    before opening the output.

    """
    global stream_fd

    # Attempts to open the stream
    try:
        stream_fd = stream.open()
    except StreamError as err:
        raise StreamError("Could not open stream: {0}".format(err))

    # Read 8192 bytes before proceeding to check for errors.
    # This is to avoid opening the output unnecessarily.
    try:
        console.logger.debug("Pre-buffering 8192 bytes")
        prebuffer = stream_fd.read(8192)
    except IOError as err:
        raise StreamError("Failed to read data from stream: {0}".format(err))

    if not prebuffer:
        raise StreamError("No data returned from stream")

    return stream_fd, prebuffer
Esempio n. 2
0
    def __init__(self, session, *streams, **options):
        if not self.is_usable(session):
            raise StreamError("cannot use FFMPEG")

        self.session = session
        self.process = None
        self.logger = session.logger.new_module("stream.mp4mux-ffmpeg")
        self.streams = streams

        self.pipes = [
            NamedPipe("ffmpeg-{0}-{1}".format(os.getpid(),
                                              random.randint(0, 1000)))
            for _ in self.streams
        ]
        self.pipe_threads = [
            threading.Thread(target=self.copy_to_pipe, args=(self, stream, np))
            for stream, np in zip(self.streams, self.pipes)
        ]

        ofmt = options.pop("format", "matroska")
        outpath = options.pop("outpath", "pipe:1")
        videocodec = session.options.get(
            "ffmpeg-video-transcode") or options.pop("vcodec", "copy")
        audiocodec = session.options.get(
            "ffmpeg-audio-transcode") or options.pop("acodec", "copy")
        metadata = options.pop("metadata", {})
        maps = options.pop("maps", [])

        self._cmd = [self.command(session), '-nostats', '-y']
        for np in self.pipes:
            self._cmd.extend(["-i", np.path])

        self._cmd.extend(['-c:v', videocodec])
        self._cmd.extend(['-c:a', audiocodec])

        for m in maps:
            self._cmd.extend(["-map", str(m)])

        for stream, data in metadata.items():
            for datum in data:
                self._cmd.extend(["-metadata:{0}".format(stream), datum])

        self._cmd.extend(['-f', ofmt, outpath])
        self.logger.debug("ffmpeg command: {0}".format(' '.join(self._cmd)))
        self.close_errorlog = False

        if session.options.get("ffmpeg-verbose"):
            self.errorlog = sys.stderr
        elif session.options.get("ffmpeg-verbose-path"):
            self.errorlog = open(session.options.get("ffmpeg-verbose-path"),
                                 "w")
            self.close_errorlog = True
        else:
            self.errorlog = compat_devnull()
Esempio n. 3
0
 def url(self):
     # If the watch timeout has passed then refresh the playlist from the API
     if int(time.time()) >= self.watch_timeout:
         for stream in self._get_stream_data():
             if stream["quality"] == self.quality:
                 self.watch_timeout = int(
                     time.time()) + stream["watch-timeout"]
                 self._url = stream["url"]
                 return self._url
         raise StreamError("cannot refresh FilmOn HLS Stream playlist")
     else:
         return self._url