class_docstr: Base AudioVideo Reader
  
  Args:
      opts: command line arguments
      is_training: Training or validation mode. Default: `False`.
class_docstr_tok: ["Base","AudioVideo","Reader","Args",":","opts",":","command","line","arguments","is_training",":","Training","or","validation","mode",".","Default",":","`","False","`","."]
docstr: Read a video file into clips and sample the clips at the specified
  video/audio frame rate. First, we read all the video and audio frames into the
  memory, where audio is at `output_audio_fps` if specified; then we sample
  `clips_per_video` clips from the entire video/audio tensor. If the desired video
  frame rate is specified, we subsample the video at frame rate
  `output_video_fps`. Despite whether the video is subsampled or not, there are
  `num_frames_per_clip` video frames in each clip.
  
  Args:
      vid_filename: The path of the video to be read.
      num_frames_per_clip: Number of frames per clip to read.
      clips_per_video: Number of clips to read for each video.
      is training: A boolean of whether the model is in training.
      output_video_fps: The frame rate of the output video. Default is -1, which
          means no resampling is required.
      output_audio_fps: The frame rate of the output audio. Default is -1, which
          means no resampling is required.
      num_samples_per_clip: Number of random samples to generate per clip.
      custom_frame_transforms: If provided, the transformation will be used
          instead of the default @BaseAVReader.get_frame_transforms.
          Note: Be careful when customizing frame transforms, because there might
              exist slight differences between the data type of frames read by
              different AVReaders before ToTensor() gets applied.
  
  Returns:
      A dictionary with video/audio as tensor and metadata. The format of
      the metadata is the following:
      {
          "video_fps": float,
          "audio_fps": int,
          "video_frame_timestamps": [num_clips x video_frames_per_clip] tensor.
      }
docstr_tok: ["Read","a","video","file","into","clips","and","sample","the","clips","at","the","specified","video\/audio","frame","rate",".","First",",","we","read","all","the","video","and","audio","frames","into","the","memory",",","where","audio","is","at","`","output_audio_fps","`","if","specified",";","then","we","sample","`","clips_per_video","`","clips","from","the","entire","video\/audio","tensor",".","If","the","desired","video","frame","rate","is","specified",",","we","subsample","the","video","at","frame","rate","`","output_video_fps","`",".","Despite","whether","the","video","is","subsampled","or","not",",","there","are","`","num_frames_per_clip","`","video","frames","in","each","clip",".","Args",":","vid_filename",":","The","path","of","the","video","to","be","read",".","num_frames_per_clip",":","Number","of","frames","per","clip","to","read",".","clips_per_video",":","Number","of","clips","to","read","for","each","video",".","is","training",":","A","boolean","of","whether","the","model","is","in","training",".","output_video_fps",":","The","frame","rate","of","the","output","video",".","Default","is","-1",",","which","means","no","resampling","is","required",".","output_audio_fps",":","The","frame","rate","of","the","output","audio",".","Default","is","-1",",","which","means","no","resampling","is","required",".","num_samples_per_clip",":","Number","of","random","samples","to","generate","per","clip",".","custom_frame_transforms",":","If","provided",",","the","transformation","will","be","used","instead","of","the","default","@","BaseAVReader.get_frame_transforms",".","Note",":","Be","careful","when","customizing","frame","transforms",",","because","there","might","exist","slight","differences","between","the","data","type","of","frames","read","by","different","AVReaders","before","ToTensor","(",")","gets","applied",".","Returns",":","A","dictionary","with","video\/audio","as","tensor","and","metadata",".","The","format","of","the","metadata","is","the","following",":","{","``","video_fps","''",":","float",",","``","audio_fps","''",":","int",",","``","video_frame_timestamps","''",":","[","num_clips","x","video_frames_per_clip","]","tensor.","}"]
code: def read_video_file_into_clips(
      self,
      vid_filename: str,
      num_frames_per_clip: int,
      clips_per_video: int,
      is_training: bool,
      video_only: bool = False,
      output_video_fps: float = -1,
      output_audio_fps: int = -1,
      num_samples_per_clip: int = 1,
      custom_frame_transforms: Optional[BaseTransformation] = None,
      *args,
      **kwargs,
  ) -> Dict:
      """Read a video file into clips and sample the clips at the specified
      video/audio frame rate. First, we read all the video and audio frames into the
      memory, where audio is at `output_audio_fps` if specified; then we sample
      `clips_per_video` clips from the entire video/audio tensor. If the desired video
      frame rate is specified, we subsample the video at frame rate
      `output_video_fps`. Despite whether the video is subsampled or not, there are
      `num_frames_per_clip` video frames in each clip.
  
      Args:
          vid_filename: The path of the video to be read.
          num_frames_per_clip: Number of frames per clip to read.
          clips_per_video: Number of clips to read for each video.
          is training: A boolean of whether the model is in training.
          output_video_fps: The frame rate of the output video. Default is -1, which
              means no resampling is required.
          output_audio_fps: The frame rate of the output audio. Default is -1, which
              means no resampling is required.
          num_samples_per_clip: Number of random samples to generate per clip.
          custom_frame_transforms: If provided, the transformation will be used
              instead of the default @BaseAVReader.get_frame_transforms.
              Note: Be careful when customizing frame transforms, because there might
                  exist slight differences between the data type of frames read by
                  different AVReaders before ToTensor() gets applied.
  
      Returns:
          A dictionary with video/audio as tensor and metadata. The format of
          the metadata is the following:
          {
              "video_fps": float,
              "audio_fps": int,
              "video_frame_timestamps": [num_clips x video_frames_per_clip] tensor.
          }
      """
  
      av_data = self.read_video(
          vid_filename,
          audio_sample_rate=output_audio_fps,
          video_only=video_only,
          custom_frame_processor=custom_frame_transforms,
      )
      torch_video = av_data["video"]
      torch_audio = av_data["audio"]
      metadata = av_data["metadata"]
      original_video_fps = metadata["video_fps"]
      audio_fps = metadata["audio_fps"]
  
      assert isinstance(
          torch_video, Tensor
      ), f"Video read from {vid_filename} expected to be a tensor."
  
      num_video_frames = torch_video.shape[0]
      # If we need to downsample the frames, read the video frames the same length in
      # second, then downsample output frames.
      if output_video_fps > 0:
          clip_duration = num_frames_per_clip / output_video_fps
          num_video_frames_to_sample = min(
              num_video_frames,
              round(clip_duration * original_video_fps),
          )
          metadata["video_fps"] = output_video_fps
      # If no frame resampling is required, read @num_frames_per_clip
      # consecutive frames.
      else:
          num_video_frames_to_sample = num_frames_per_clip
          clip_duration = num_frames_per_clip / original_video_fps
  
      if torch_audio is None:
          num_audio_frames = None
      else:
          num_audio_frames = torch_audio.shape[0]
          audio_sec = num_audio_frames / audio_fps
          video_sec = num_video_frames / original_video_fps
          # Making sure audio and video are of same length.
          if numpy.fabs(audio_sec - video_sec) >= 0.1:
              raise VideoDurationDoesNotMatchAudioDurationError(
                  f"Audio duration {audio_sec} video duration {video_sec} might be different."
              )
  
      if num_video_frames >= num_frames_per_clip:
          sampling_fn = (
              self.random_sampling
              if is_training
              else self.uniform_sampling
          )
          vclip_ids, aclip_ids = sampling_fn(
              total_video_frames=num_video_frames,
              video_frames_per_clip=num_video_frames_to_sample,
              clips_per_video=clips_per_video,
              total_audio_frames=num_audio_frames,
          )
      else:
          vclip_ids = aclip_ids = None
  
      num_samples_per_clip = num_samples_per_clip if is_training else 1
      video_clips, metadata = self._generate_video_clips(
          full_video_tensor=torch_video,
          vclip_ids=vclip_ids,
          metadata=metadata,
          clips_per_video=clips_per_video,
          num_frames_per_clip=num_frames_per_clip,
          original_video_fps=original_video_fps,
          output_video_fps=output_video_fps,
          is_training=is_training,
          num_samples_per_clip=num_samples_per_clip,
      )
  
      if torch_audio is None:
          audio_clips = None
      else:
          audio_clips = self._generate_audio_clips(
              full_audio_tensor=torch_audio,
              aclip_ids=aclip_ids,
              clip_duration=clip_duration,
              clips_per_video=clips_per_video,
              audio_fps=audio_fps,
              num_samples_per_clip=num_samples_per_clip,
          )
      return {
          "video": video_clips,
          "audio": audio_clips,
          "metadata": metadata,
      }
  
imports: import argparse
  import random
  from typing import Dict, Optional, Tuple
  import av
  import numpy
  import torch
  import torch.nn.functional
  from torch import Tensor
  from data.transforms import BaseTransformation
  from data.transforms import image_pil
  from data.transforms.common import Compose
  from options.utils import extend_selected_args_with_prefix, extract_opts_with_prefix_replacement
  from utils import logger
label_desc: Use image node_id 10 for calling the BaseAVReader obj's underlying member method code with example usage: obj.read_video_file_into_clips(vid_filename, num_frames_per_clip, clips_per_video, is_training, video_only, output_video_fps, output_audio_fps, num_samples_per_clip, custom_frame_transforms) and returns: dict