@@ -41,21 +41,48 @@ class VideoReader:
41
41
container.
42
42
43
43
Example:
44
- The following examples creates :mod:`Video ` object, seeks into 2s
44
+ The following examples creates a :mod:`VideoReader ` object, seeks into 2s
45
45
point, and returns a single frame::
46
46
import torchvision
47
47
video_path = "path_to_a_test_video"
48
48
49
49
reader = torchvision.io.VideoReader(video_path, "video")
50
50
reader.seek(2.0)
51
- frame, timestamp = next(reader)
51
+ frame = next(reader)
52
+
53
+ :mod:`VideoReader` implements the iterable API, which makes it suitable to
54
+ using it in conjunction with :mod:`itertools` for more advanced reading.
55
+ As such, we can use a :mod:`VideoReader` instance inside for loops::
56
+ reader.seek(2)
57
+ for frame in reader:
58
+ frames.append(frame['data'])
59
+ # additionally, `seek` implements a fluent API, so we can do
60
+ for frame in reader.seek(2):
61
+ frames.append(frame['data'])
62
+ With :mod:`itertools`, we can read all frames between 2 and 5 seconds with the
63
+ following code::
64
+ for frame in itertools.takewhile(lambda x: x['pts'] <= 5, reader.seek(2)):
65
+ frames.append(frame['data'])
66
+ and similarly, reading 10 frames after the 2s timestamp can be achieved
67
+ as follows::
68
+ for frame in itertools.islice(reader.seek(2), 10):
69
+ frames.append(frame['data'])
70
+
71
+ .. note::
72
+
73
+ Each stream descriptor consists of two parts: stream type (e.g. 'video') and
74
+ a unique stream id (which are determined by the video encoding).
75
+ In this way, if the video contaner contains multiple
76
+ streams of the same type, users can acces the one they want.
77
+ If only stream type is passed, the decoder auto-detects first stream of that type.
52
78
53
79
Args:
54
80
55
81
path (string): Path to the video file in supported format
56
82
57
- stream (string, optional): descriptor of the required stream. Defaults to "video:0"
58
- Currently available options include :mod:`['video', 'audio', 'cc', 'sub']`
83
+ stream (string, optional): descriptor of the required stream, followed by the stream id,
84
+ in the format ``{stream_type}:{stream_id}``. Defaults to ``"video:0"``.
85
+ Currently available options include ``['video', 'audio']``
59
86
"""
60
87
61
88
def __init__ (self , path , stream = "video" ):
@@ -67,13 +94,14 @@ def __next__(self):
67
94
"""Decodes and returns the next frame of the current stream
68
95
69
96
Returns:
70
- ([torch.Tensor, float]): list containing decoded frame and corresponding timestamp
97
+ (dict): a dictionary with fields ``data`` and ``pts``
98
+ containing decoded frame and corresponding timestamp
71
99
72
100
"""
73
101
frame , pts = self ._c .next ()
74
102
if frame .numel () == 0 :
75
103
raise StopIteration
76
- return frame , pts
104
+ return { "data" : frame , " pts" : pts }
77
105
78
106
def __iter__ (self ):
79
107
return self
@@ -88,7 +116,7 @@ def seek(self, time_s: float):
88
116
Current implementation is the so-called precise seek. This
89
117
means following seek, call to :mod:`next()` will return the
90
118
frame with the exact timestamp if it exists or
91
- the first frame with timestamp larger than time_s.
119
+ the first frame with timestamp larger than `` time_s`` .
92
120
"""
93
121
self ._c .seek (time_s )
94
122
return self
@@ -106,8 +134,8 @@ def set_current_stream(self, stream: str):
106
134
Explicitly define the stream we are operating on.
107
135
108
136
Args:
109
- stream (string): descriptor of the required stream. Defaults to "video:0"
110
- Currently available stream types include :mod:` ['video', 'audio', 'cc', 'sub'] `.
137
+ stream (string): descriptor of the required stream. Defaults to `` "video:0"``
138
+ Currently available stream types include `` ['video', 'audio']` `.
111
139
Each descriptor consists of two parts: stream type (e.g. 'video') and
112
140
a unique stream id (which are determined by video encoding).
113
141
In this way, if the video contaner contains multiple
0 commit comments