'Attempts to extract available streams.
Returns a :class:`dict` containing the streams, where the key is
the name of the stream, most commonly the quality and the value
is a :class:`Stream` object.
The result can contain the synonyms **best** and **worst** which
points to the streams which are likely to be of highest and
lowest quality respectively.
If multiple streams with the same name are found, the order of
streams specified in *stream_types* will determine which stream
gets to keep the name while the rest will be renamed to
"<name>_<stream type>".
The synonyms can be fine tuned with the *sorting_excludes*
parameter. This can be either of these types:
- A list of filter expressions in the format
*[operator]<value>*. For example the filter ">480p" will
exclude streams ranked higher than "480p" from the list
used in the synonyms ranking. Valid operators are >, >=, <
and <=. If no operator is specified then equality will be
tested.
- A function that is passed to filter() with a list of
stream names as input.
:param stream_types: A list of stream types to return.
:param sorting_excludes: Specify which streams to exclude from
the best/worst synonyms.
.. versionchanged:: 1.4.2
Added *priority* parameter.
.. versionchanged:: 1.5.0
Renamed *priority* to *stream_types* and changed behaviour
slightly.
.. versionchanged:: 1.5.0
Added *sorting_excludes* parameter.
.. versionchanged:: 1.6.0
*sorting_excludes* can now be a list of filter expressions
or a function that is passed to filter().'

def streams(self, stream_types=None, sorting_excludes=None):

    try:
        ostreams = self._get_streams()
        if isinstance(ostreams, dict):
            ostreams = ostreams.items()
        if ostreams:
            ostreams = list(ostreams)
    except NoStreamsError:
        return {}
    except (IOError, OSError, ValueError) as err:
        raise PluginError(err)
    if (not ostreams):
        return {}
    if (stream_types is None):
        stream_types = self.default_stream_types(ostreams)
    sorted_streams = sorted(iterate_streams(ostreams), key=partial(stream_type_priority, stream_types))
    streams = {}
    for (name, stream) in sorted_streams:
        stream_type = type(stream).shortname()
        if (stream_type not in stream_types):
            continue
        existing = streams.get(name)
        if existing:
            existing_stream_type = type(existing).shortname()
            if (existing_stream_type != stream_type):
                name = '{0}_{1}'.format(name, stream_type)
            if (name in streams):
                name = '{0}_alt'.format(name)
                num_alts = len(list(filter((lambda n: n.startswith(name)), streams.keys())))
                if (num_alts >= 2):
                    continue
                elif (num_alts > 0):
                    name = '{0}{1}'.format(name, (num_alts + 1))
        match = re.match('([A-z0-9_+]+)', name)
        if match:
            name = match.group(1)
        else:
            self.logger.debug("The    stream    '{0}'    has    been    ignored    since    it    is    badly    named.", name)
            continue
        streams[name.lower()] = stream
    stream_weight_only = (lambda s: (self.stream_weight(s)[0] or ((len(streams) == 1) and 1)))
    stream_names = filter(stream_weight_only, streams.keys())
    sorted_streams = sorted(stream_names, key=stream_weight_only)
    if isinstance(sorting_excludes, list):
        for expr in sorting_excludes:
            filter_func = stream_sorting_filter(expr, self.stream_weight)
            sorted_streams = list(filter(filter_func, sorted_streams))
    elif callable(sorting_excludes):
        sorted_streams = list(filter(sorting_excludes, sorted_streams))
    if (len(sorted_streams) > 0):
        best = sorted_streams[(-1)]
        worst = sorted_streams[0]
        streams['best'] = streams[best]
        streams['worst'] = streams[worst]
    return streams
