class_docstr: Fine-grained video-reading API.
  Supports frame-by-frame reading of various streams from a single video
  container. Much like previous video_reader API it supports the following
  backends: video_reader, pyav, and cuda.
  Backends can be set via `torchvision.set_video_backend` function.
  
  .. betastatus:: VideoReader class
  
  Example:
      The following examples creates a :mod:`VideoReader` object, seeks into 2s
      point, and returns a single frame::
  
          import torchvision
          video_path = "path_to_a_test_video"
          reader = torchvision.io.VideoReader(video_path, "video")
          reader.seek(2.0)
          frame = next(reader)
  
      :mod:`VideoReader` implements the iterable API, which makes it suitable to
      using it in conjunction with :mod:`itertools` for more advanced reading.
      As such, we can use a :mod:`VideoReader` instance inside for loops::
  
          reader.seek(2)
          for frame in reader:
              frames.append(frame['data'])
          # additionally, `seek` implements a fluent API, so we can do
          for frame in reader.seek(2):
              frames.append(frame['data'])
  
      With :mod:`itertools`, we can read all frames between 2 and 5 seconds with the
      following code::
  
          for frame in itertools.takewhile(lambda x: x['pts'] <= 5, reader.seek(2)):
              frames.append(frame['data'])
  
      and similarly, reading 10 frames after the 2s timestamp can be achieved
      as follows::
  
          for frame in itertools.islice(reader.seek(2), 10):
              frames.append(frame['data'])
  
  .. note::
  
      Each stream descriptor consists of two parts: stream type (e.g. 'video') and
      a unique stream id (which are determined by the video encoding).
      In this way, if the video container contains multiple
      streams of the same type, users can access the one they want.
      If only stream type is passed, the decoder auto-detects first stream of that type.
  
  Args:
      src (string, bytes object, or tensor): The media source.
          If string-type, it must be a file path supported by FFMPEG.
          If bytes, should be an in-memory representation of a file supported by FFMPEG.
          If Tensor, it is interpreted internally as byte buffer.
          It must be one-dimensional, of type ``torch.uint8``.
  
      stream (string, optional): descriptor of the required stream, followed by the stream id,
          in the format ``{stream_type}:{stream_id}``. Defaults to ``"video:0"``.
          Currently available options include ``['video', 'audio']``
  
      num_threads (int, optional): number of threads used by the codec to decode video.
          Default value (0) enables multithreading with codec-dependent heuristic. The performance
          will depend on the version of FFMPEG codecs supported.
class_docstr_tok: ["Fine-grained","video-reading","API",".","Supports","frame-by-frame","reading","of","various","streams","from","a","single","video","container",".","Much","like","previous","video_reader","API","it","supports","the","following","backends",":","video_reader",",","pyav",",","and","cuda",".","Backends","can","be","set","via","`","torchvision.set_video_backend","`","function",".","..","betastatus",":",":","VideoReader","class","Example",":","The","following","examples","creates","a",":","mod",":","`","VideoReader","`","object",",","seeks","into","2s","point",",","and","returns","a","single","frame",":",":","import","torchvision","video_path","=","``","path_to_a_test_video","''","reader","=","torchvision.io.VideoReader","(","video_path",",","``","video","''",")","reader.seek","(","2.0",")","frame","=","next","(","reader",")",":","mod",":","`","VideoReader","`","implements","the","iterable","API",",","which","makes","it","suitable","to","using","it","in","conjunction","with",":","mod",":","`","itertools","`","for","more","advanced","reading",".","As","such",",","we","can","use","a",":","mod",":","`","VideoReader","`","instance","inside","for","loops",":",":","reader.seek","(","2",")","for","frame","in","reader",":","frames.append","(","frame","[","'data","'","]",")","#","additionally",",","`","seek","`","implements","a","fluent","API",",","so","we","can","do","for","frame","in","reader.seek","(","2",")",":","frames.append","(","frame","[","'data","'","]",")","With",":","mod",":","`","itertools","`",",","we","can","read","all","frames","between","2","and","5","seconds","with","the","following","code",":",":","for","frame","in","itertools.takewhile","(","lambda","x",":","x","[","'pts","'","]","<","=","5",",","reader.seek","(","2",")",")",":","frames.append","(","frame","[","'data","'","]",")","and","similarly",",","reading","10","frames","after","the","2s","timestamp","can","be","achieved","as","follows",":",":","for","frame","in","itertools.islice","(","reader.seek","(","2",")",",","10",")",":","frames.append","(","frame","[","'data","'","]",")","..","note",":",":","Each","stream","descriptor","consists","of","two","parts",":","stream","type","(","e.g",".","'video","'",")","and","a","unique","stream","id","(","which","are","determined","by","the","video","encoding",")",".","In","this","way",",","if","the","video","container","contains","multiple","streams","of","the","same","type",",","users","can","access","the","one","they","want",".","If","only","stream","type","is","passed",",","the","decoder","auto-detects","first","stream","of","that","type",".","Args",":","src","(","string",",","bytes","object",",","or","tensor",")",":","The","media","source",".","If","string-type",",","it","must","be","a","file","path","supported","by","FFMPEG",".","If","bytes",",","should","be","an","in-memory","representation","of","a","file","supported","by","FFMPEG",".","If","Tensor",",","it","is","interpreted","internally","as","byte","buffer",".","It","must","be","one-dimensional",",","of","type","``","torch.uint8","``",".","stream","(","string",",","optional",")",":","descriptor","of","the","required","stream",",","followed","by","the","stream","id",",","in","the","format","``","{","stream_type","}",":","{","stream_id","}","``",".","Defaults","to","``","``","video:0","''","``",".","Currently","available","options","include","``","[","'video","'",",","'audio","'","]","``","num_threads","(","int",",","optional",")",":","number","of","threads","used","by","the","codec","to","decode","video",".","Default","value","(","0",")","enables","multithreading","with","codec-dependent","heuristic",".","The","performance","will","depend","on","the","version","of","FFMPEG","codecs","supported","."]
code: def __init__(
      self,
      src: str,
      stream: str = "video",
      num_threads: int = 0,
  ) -> None:
      _log_api_usage_once(self)
      from .. import get_video_backend
  
      self.backend = get_video_backend()
      if isinstance(src, str):
          if not src:
              raise ValueError("src cannot be empty")
      elif isinstance(src, bytes):
          if self.backend in ["cuda"]:
              raise RuntimeError(
                  "VideoReader cannot be initialized from bytes object when using cuda or pyav backend."
              )
          elif self.backend == "pyav":
              src = io.BytesIO(src)
          else:
              with warnings.catch_warnings():
                  # Ignore the warning because we actually don't modify the buffer in this function
                  warnings.filterwarnings(
                      "ignore",
                      message="The given buffer is not writable",
                  )
                  src = torch.frombuffer(src, dtype=torch.uint8)
      elif isinstance(src, torch.Tensor):
          if self.backend in ["cuda", "pyav"]:
              raise RuntimeError(
                  "VideoReader cannot be initialized from Tensor object when using cuda or pyav backend."
              )
      else:
          raise ValueError(
              f"src must be either string, Tensor or bytes object. Got {type(src)}"
          )
  
      if self.backend == "cuda":
          device = torch.device("cuda")
          self._c = torch.classes.torchvision.GPUDecoder(src, device)
  
      elif self.backend == "video_reader":
          if isinstance(src, str):
              self._c = torch.classes.torchvision.Video(
                  src, stream, num_threads
              )
          elif isinstance(src, torch.Tensor):
              self._c = torch.classes.torchvision.Video("", "", 0)
              self._c.init_from_memory(src, stream, num_threads)
  
      elif self.backend == "pyav":
          self.container = av.open(src, metadata_errors="ignore")
          # TODO: load metadata
          stream_type = stream.split(":")[0]
          stream_id = (
              0
              if len(stream.split(":")) == 1
              else int(stream.split(":")[1])
          )
          self.pyav_stream = {stream_type: stream_id}
          self._c = self.container.decode(**self.pyav_stream)
  
          # TODO: add extradata exception
  
      else:
          raise RuntimeError(
              "Unknown video backend: {}".format(self.backend)
          )
  
file_path: vision/torchvision/io/video_reader.py
imports: import io
  import warnings
  from typing import Any, Dict, Iterator
  import torch
  from ..utils import _log_api_usage_once
  from ._video_opt import _HAS_VIDEO_OPT
label_desc: Use image node_id 1 to create a new VideoReader object  with example: obj = VideoReader(src, stream, num_threads)