# Buggy code
def parse_video_stream_data(self, line):
    """Parses data from "Stream ... Video" line."""
    global_data, stream_data = ({"video_found": True}, {})

    try:
        match_video_size = re.search(r" (\d+)x(\d+)[,\s]", line)
        if match_video_size:
            # size, of the form 460x320 (w x h)
            stream_data["size"] = [int(num) for num in match_video_size.groups()]
    except Exception:
        raise IOError(
            (
                "MoviePy error: failed to read video dimensions in"
                " file '%s'.\nHere are the file infos returned by"
                "ffmpeg:\n\n%s"
            )
            % (self.filename, self.infos)
        )

    match_bitrate = re.search(r"(\d+) kb/s", line)
    stream_data["bitrate"] = int(match_bitrate.group(1)) if match_bitrate else None

    # Get the frame rate. Sometimes it's 'tbr', sometimes 'fps', sometimes
    # tbc, and sometimes tbc/2...
    # Current policy: Trust fps first, then tbr unless fps_source is
    # specified as 'tbr' in which case try tbr then fps

    # If result is near from x*1000/1001 where x is 23,24,25,50,
    # replace by x*1000/1001 (very common case for the fps).

    if self.fps_source == "fps":
        try:
            fps = self.parse_fps(line)
        except (AttributeError, ValueError):
            fps = self.parse_tbr(line)
    elif self.fps_source == "tbr":
        try:
            fps = self.parse_tbr(line)
        except (AttributeError, ValueError):
            fps = self.parse_fps(line)
    else:
        raise ValueError(
            ("fps source '%s' not supported parsing the video '%s'")
            % (self.fps_source, self.filename)
        )

    # It is known that a fps of 24 is often written as 24000/1001
    # but then ffmpeg nicely rounds it to 23.98, which we hate.
    coef = 1000.0 / 1001.0
    for x in [23, 24, 25, 30, 50]:
        if (fps != x) and abs(fps - x * coef) < 0.01:
            fps = x * coef
    stream_data["fps"] = fps

    if self._current_stream["default"]:
        global_data["video_size"] = stream_data.get("size", None)
        global_data["video_bitrate"] = stream_data.get("bitrate", None)
        global_data["video_fps"] = stream_data["fps"]
    return (global_data, stream_data)


# Traceback (AttributeError)
Exception ignored in: <bound method FFMPEG_AudioReader.__del__ of <moviepy.audio.io.readers.FFMPEG_AudioReader object at 0x7fc339261cf8>>
Traceback (most recent call last):
File "/home/vagrant/.tox/py36/lib/python3.6/site-packages/moviepy/audio/io/readers.py", line 264, in __del__
self.close()
File "/home/vagrant/.tox/py36/lib/python3.6/site-packages/moviepy/audio/io/readers.py", line 254, in close
if self.proc:
AttributeError: 'FFMPEG_AudioReader' object has no attribute 'proc'

# Fixed code
def parse_video_stream_data(self, line):
    """Parses data from "Stream ... Video" line."""
    global_data, stream_data = ({"video_found": True}, {})

    try:
        match_video_size = re.search(r" (\d+)x(\d+)[,\s]", line)
        if match_video_size:
            # size, of the form 460x320 (w x h)
            stream_data["size"] = [int(num) for num in match_video_size.groups()]
    except Exception:
        raise IOError(
            (
                "MoviePy error: failed to read video dimensions in"
                " file '%s'.\nHere are the file infos returned by"
                "ffmpeg:\n\n%s"
            )
            % (self.filename, self.infos)
        )

    match_bitrate = re.search(r"(\d+) kb/s", line)
    stream_data["bitrate"] = int(match_bitrate.group(1)) if match_bitrate else None

    # Get the frame rate. Sometimes it's 'tbr', sometimes 'fps', sometimes
    # tbc, and sometimes tbc/2...
    # Current policy: Trust fps first, then tbr unless fps_source is
    # specified as 'tbr' in which case try tbr then fps

    # If result is near from x*1000/1001 where x is 23,24,25,50,
    # replace by x*1000/1001 (very common case for the fps).

    if self.fps_source == "fps":
        try:
            fps = self.parse_fps(line)
        except (AttributeError, ValueError):
            fps = self.parse_tbr(line)
    elif self.fps_source == "tbr":
        try:
            fps = self.parse_tbr(line)
        except (AttributeError, ValueError):
            fps = self.parse_fps(line)
    else:
        raise ValueError(
            ("fps source '%s' not supported parsing the video '%s'")
            % (self.fps_source, self.filename)
        )

    # It is known that a fps of 24 is often written as 24000/1001
    # but then ffmpeg nicely rounds it to 23.98, which we hate.
    coef = 1000.0 / 1001.0
    for x in [23, 24, 25, 30, 50]:
        if (fps != x) and abs(fps - x * coef) < 0.01:
            fps = x * coef
    stream_data["fps"] = fps

    if self._current_stream["default"] or "video_size" not in self.result:
        global_data["video_size"] = stream_data.get("size", None)
    if self._current_stream["default"] or "video_bitrate" not in self.result:
        global_data["video_bitrate"] = stream_data.get("bitrate", None)
    if self._current_stream["default"] or "video_fps" not in self.result:
        global_data["video_fps"] = stream_data["fps"]

    return (global_data, stream_data)