@@ -124,13 +124,17 @@ def _read_from_stream(container, start_offset, end_offset, pts_unit, stream, str
124
124
# print("Corrupted file?", container.name)
125
125
return []
126
126
buffer_count = 0
127
- for idx , frame in enumerate (container .decode (** stream_name )):
128
- frames [frame .pts ] = frame
129
- if frame .pts >= end_offset :
130
- if should_buffer and buffer_count < max_buffer_size :
131
- buffer_count += 1
132
- continue
133
- break
127
+ try :
128
+ for idx , frame in enumerate (container .decode (** stream_name )):
129
+ frames [frame .pts ] = frame
130
+ if frame .pts >= end_offset :
131
+ if should_buffer and buffer_count < max_buffer_size :
132
+ buffer_count += 1
133
+ continue
134
+ break
135
+ except av .AVError :
136
+ # TODO add a warning
137
+ pass
134
138
# ensure that the results are sorted wrt the pts
135
139
result = [frames [i ] for i in sorted (frames ) if start_offset <= frames [i ].pts <= end_offset ]
136
140
if start_offset > 0 and start_offset not in frames :
@@ -193,25 +197,39 @@ def read_video(filename, start_pts=0, end_pts=None, pts_unit='pts'):
193
197
raise ValueError ("end_pts should be larger than start_pts, got "
194
198
"start_pts={} and end_pts={}" .format (start_pts , end_pts ))
195
199
196
- container = av .open (filename , metadata_errors = 'ignore' )
197
200
info = {}
198
-
199
201
video_frames = []
200
- if container .streams .video :
201
- video_frames = _read_from_stream (container , start_pts , end_pts , pts_unit ,
202
- container .streams .video [0 ], {'video' : 0 })
203
- info ["video_fps" ] = float (container .streams .video [0 ].average_rate )
204
202
audio_frames = []
205
- if container .streams .audio :
206
- audio_frames = _read_from_stream (container , start_pts , end_pts , pts_unit ,
207
- container .streams .audio [0 ], {'audio' : 0 })
208
- info ["audio_fps" ] = container .streams .audio [0 ].rate
209
203
210
- container .close ()
204
+ try :
205
+ container = av .open (filename , metadata_errors = 'ignore' )
206
+ except av .AVError :
207
+ # TODO raise a warning?
208
+ pass
209
+ else :
210
+ if container .streams .video :
211
+ video_frames = _read_from_stream (container , start_pts , end_pts , pts_unit ,
212
+ container .streams .video [0 ], {'video' : 0 })
213
+ video_fps = container .streams .video [0 ].average_rate
214
+ # guard against potentially corrupted files
215
+ if video_fps is not None :
216
+ info ["video_fps" ] = float (video_fps )
217
+
218
+ if container .streams .audio :
219
+ audio_frames = _read_from_stream (container , start_pts , end_pts , pts_unit ,
220
+ container .streams .audio [0 ], {'audio' : 0 })
221
+ info ["audio_fps" ] = container .streams .audio [0 ].rate
222
+
223
+ container .close ()
211
224
212
225
vframes = [frame .to_rgb ().to_ndarray () for frame in video_frames ]
213
226
aframes = [frame .to_ndarray () for frame in audio_frames ]
214
- vframes = torch .as_tensor (np .stack (vframes ))
227
+
228
+ if vframes :
229
+ vframes = torch .as_tensor (np .stack (vframes ))
230
+ else :
231
+ vframes = torch .empty ((0 , 1 , 1 , 3 ), dtype = torch .uint8 )
232
+
215
233
if aframes :
216
234
aframes = np .concatenate (aframes , 1 )
217
235
aframes = torch .as_tensor (aframes )
@@ -255,21 +273,30 @@ def read_video_timestamps(filename, pts_unit='pts'):
255
273
"""
256
274
_check_av_available ()
257
275
258
- container = av .open (filename , metadata_errors = 'ignore' )
259
-
260
276
video_frames = []
261
277
video_fps = None
262
- if container .streams .video :
263
- video_stream = container .streams .video [0 ]
264
- video_time_base = video_stream .time_base
265
- if _can_read_timestamps_from_packets (container ):
266
- # fast path
267
- video_frames = [x for x in container .demux (video = 0 ) if x .pts is not None ]
268
- else :
269
- video_frames = _read_from_stream (container , 0 , float ("inf" ), pts_unit ,
270
- video_stream , {'video' : 0 })
271
- video_fps = float (video_stream .average_rate )
272
- container .close ()
278
+
279
+ try :
280
+ container = av .open (filename , metadata_errors = 'ignore' )
281
+ except av .AVError :
282
+ # TODO add a warning
283
+ pass
284
+ else :
285
+ if container .streams .video :
286
+ video_stream = container .streams .video [0 ]
287
+ video_time_base = video_stream .time_base
288
+ if _can_read_timestamps_from_packets (container ):
289
+ # fast path
290
+ video_frames = [x for x in container .demux (video = 0 ) if x .pts is not None ]
291
+ else :
292
+ video_frames = _read_from_stream (container , 0 , float ("inf" ), pts_unit ,
293
+ video_stream , {'video' : 0 })
294
+ video_fps = float (video_stream .average_rate )
295
+ container .close ()
296
+
297
+ pts = [x .pts for x in video_frames ]
298
+
273
299
if pts_unit == 'sec' :
274
- return [x .pts * video_time_base for x in video_frames ], video_fps
275
- return [x .pts for x in video_frames ], video_fps
300
+ pts = [x * video_time_base for x in pts ]
301
+
302
+ return pts , video_fps
0 commit comments