44# This source code is licensed under the BSD-style license found in the
55# LICENSE file in the root directory of this source tree.
66
7+
78import dataclasses
89import json
910import pathlib
1011from dataclasses import dataclass
1112from fractions import Fraction
12- from typing import List , Optional , Union
1313
1414import torch
1515
2525
2626@dataclass
2727class StreamMetadata :
28- duration_seconds_from_header : Optional [ float ]
28+ duration_seconds_from_header : float | None
2929 """Duration of the stream, in seconds, obtained from the header (float or
3030 None). This could be inaccurate."""
31- begin_stream_seconds_from_header : Optional [ float ]
31+ begin_stream_seconds_from_header : float | None
3232 """Beginning of the stream, in seconds, obtained from the header (float or
3333 None). Usually, this is equal to 0."""
34- bit_rate : Optional [ float ]
34+ bit_rate : float | None
3535 """Bit rate of the stream, in seconds (float or None)."""
36- codec : Optional [ str ]
36+ codec : str | None
3737 """Codec (str or None)."""
3838 stream_index : int
3939 """Index of the stream that this metadata refers to (int)."""
4040
4141 # Computed fields (computed in C++ with fallback logic)
42- duration_seconds : Optional [ float ]
42+ duration_seconds : float | None
4343 """Duration of the stream in seconds. We try to calculate the duration
4444 from the actual frames if a :term:`scan` was performed. Otherwise we
4545 fall back to ``duration_seconds_from_header``. If that value is also None,
4646 we instead calculate the duration from ``num_frames_from_header`` and
4747 ``average_fps_from_header``. If all of those are unavailable, we fall back
4848 to the container-level ``duration_seconds_from_header``.
4949 """
50- begin_stream_seconds : Optional [ float ]
50+ begin_stream_seconds : float | None
5151 """Beginning of the stream, in seconds (float). Conceptually, this
5252 corresponds to the first frame's :term:`pts`. If a :term:`scan` was performed
5353 and ``begin_stream_seconds_from_content`` is not None, then it is returned.
@@ -65,12 +65,12 @@ def __repr__(self):
6565class VideoStreamMetadata (StreamMetadata ):
6666 """Metadata of a single video stream."""
6767
68- begin_stream_seconds_from_content : Optional [ float ]
68+ begin_stream_seconds_from_content : float | None
6969 """Beginning of the stream, in seconds (float or None).
7070 Conceptually, this corresponds to the first frame's :term:`pts`. It is only
7171 computed when a :term:`scan` is done as min(frame.pts) across all frames in
7272 the stream. Usually, this is equal to 0."""
73- end_stream_seconds_from_content : Optional [ float ]
73+ end_stream_seconds_from_content : float | None
7474 """End of the stream, in seconds (float or None).
7575 Conceptually, this corresponds to last_frame.pts + last_frame.duration. It
7676 is only computed when a :term:`scan` is done as max(frame.pts +
@@ -81,42 +81,42 @@ class VideoStreamMetadata(StreamMetadata):
8181 simply indexing the :class:`~torchcodec.decoders.VideoDecoder` object with
8282 ``[-1]``.
8383 """
84- width : Optional [ int ]
84+ width : int | None
8585 """Width of the frames (int or None)."""
86- height : Optional [ int ]
86+ height : int | None
8787 """Height of the frames (int or None)."""
88- num_frames_from_header : Optional [ int ]
88+ num_frames_from_header : int | None
8989 """Number of frames, from the stream's metadata. This is potentially
9090 inaccurate. We recommend using the ``num_frames`` attribute instead.
9191 (int or None)."""
92- num_frames_from_content : Optional [ int ]
92+ num_frames_from_content : int | None
9393 """Number of frames computed by TorchCodec by scanning the stream's
9494 content (the scan doesn't involve decoding). This is more accurate
9595 than ``num_frames_from_header``. We recommend using the
9696 ``num_frames`` attribute instead. (int or None)."""
97- average_fps_from_header : Optional [ float ]
97+ average_fps_from_header : float | None
9898 """Averate fps of the stream, obtained from the header (float or None).
9999 We recommend using the ``average_fps`` attribute instead."""
100- pixel_aspect_ratio : Optional [ Fraction ]
100+ pixel_aspect_ratio : Fraction | None
101101 """Pixel Aspect Ratio (PAR), also known as Sample Aspect Ratio
102102 (SAR --- not to be confused with Storage Aspect Ratio, also SAR),
103103 is the ratio between the width and height of each pixel
104104 (``fractions.Fraction`` or None)."""
105105
106106 # Computed fields (computed in C++ with fallback logic)
107- end_stream_seconds : Optional [ float ]
107+ end_stream_seconds : float | None
108108 """End of the stream, in seconds (float or None).
109109 Conceptually, this corresponds to last_frame.pts + last_frame.duration.
110110 If :term:`scan` was performed and``end_stream_seconds_from_content`` is not None, then that value is
111111 returned. Otherwise, returns ``duration_seconds``.
112112 """
113- num_frames : Optional [ int ]
113+ num_frames : int | None
114114 """Number of frames in the stream (int or None).
115115 This corresponds to ``num_frames_from_content`` if a :term:`scan` was made,
116116 otherwise it corresponds to ``num_frames_from_header``. If that value is also
117117 None, the number of frames is calculated from the duration and the average fps.
118118 """
119- average_fps : Optional [ float ]
119+ average_fps : float | None
120120 """Average fps of the stream. If a :term:`scan` was perfomed, this is
121121 computed from the number of frames and the duration of the stream.
122122 Otherwise we fall back to ``average_fps_from_header``.
@@ -130,11 +130,11 @@ def __repr__(self):
130130class AudioStreamMetadata (StreamMetadata ):
131131 """Metadata of a single audio stream."""
132132
133- sample_rate : Optional [ int ]
133+ sample_rate : int | None
134134 """The original sample rate."""
135- num_channels : Optional [ int ]
135+ num_channels : int | None
136136 """The number of channels (1 for mono, 2 for stereo, etc.)"""
137- sample_format : Optional [ str ]
137+ sample_format : str | None
138138 """The original sample format, as described by FFmpeg. E.g. 'fltp', 's32', etc."""
139139
140140 def __repr__ (self ):
@@ -143,19 +143,19 @@ def __repr__(self):
143143
144144@dataclass
145145class ContainerMetadata :
146- duration_seconds_from_header : Optional [ float ]
147- bit_rate_from_header : Optional [ float ]
148- best_video_stream_index : Optional [ int ]
149- best_audio_stream_index : Optional [ int ]
146+ duration_seconds_from_header : float | None
147+ bit_rate_from_header : float | None
148+ best_video_stream_index : int | None
149+ best_audio_stream_index : int | None
150150
151- streams : List [StreamMetadata ]
151+ streams : list [StreamMetadata ]
152152
153153 @property
154- def duration_seconds (self ) -> Optional [ float ] :
154+ def duration_seconds (self ) -> float | None :
155155 raise NotImplementedError ("Decide on logic and implement this!" )
156156
157157 @property
158- def bit_rate (self ) -> Optional [ float ] :
158+ def bit_rate (self ) -> float | None :
159159 raise NotImplementedError ("Decide on logic and implement this!" )
160160
161161 @property
@@ -195,7 +195,7 @@ def get_container_metadata(decoder: torch.Tensor) -> ContainerMetadata:
195195 """
196196
197197 container_dict = json .loads (_get_container_json_metadata (decoder ))
198- streams_metadata : List [StreamMetadata ] = []
198+ streams_metadata : list [StreamMetadata ] = []
199199 for stream_index in range (container_dict ["numStreams" ]):
200200 stream_dict = json .loads (_get_stream_json_metadata (decoder , stream_index ))
201201 common_meta = dict (
@@ -255,7 +255,7 @@ def get_container_metadata(decoder: torch.Tensor) -> ContainerMetadata:
255255
256256
257257def get_container_metadata_from_header (
258- filename : Union [ str , pathlib .Path ]
258+ filename : str | pathlib .Path ,
259259) -> ContainerMetadata :
260260 return get_container_metadata (
261261 create_from_file (str (filename ), seek_mode = "approximate" )
0 commit comments