@@ -78,7 +78,7 @@ def __getattr__(name):
7878
7979def open (
8080 url_fg ,
81- mode = "" ,
81+ mode ,
8282 rate_in = None ,
8383 shape_in = None ,
8484 dtype_in = None ,
@@ -219,111 +219,120 @@ def open(
219219 is_fg = kwds .get ("f_in" , None ) == "lavfi"
220220 url_fg = (url_fg ,)
221221
222- audio = "a" in mode
223- video = "v" in mode
224- read = "r" in mode
225- write = "w" in mode
226- filter = "f" in mode
227- # backwards = "b" in mode
228222 unk = set (mode ) - set ("avrwf" )
229223 if unk :
230- raise Exception (
224+ raise ValueError (
231225 f"Invalid FFmpeg streaming mode: { mode } . Unknown mode { unk } specified."
232226 )
233227
234- if read + write + filter > 1 :
235- raise Exception (
236- f"Invalid FFmpeg streaming mode: { mode } . Only 1 of 'rwf' may be specified."
228+ read = "r" in mode
229+ write = "w" in mode
230+ filter = "f" in mode
231+
232+ if read + write + filter != 1 :
233+ raise ValueError (
234+ f"Invalid FFmpeg streaming mode argument: { mode } . It must contain one and only one of 'rwf'."
237235 )
238236
239- if (read or write or filter ):
240- # convert unused rate argument to ffmpeg option
241- if read and rate_in is not None :
242- kwds ['r_in' if video else 'ar_in' ] = rate_in
243- rate_in = None
244- elif write and rate is not None :
245- kwds ['r' if video else 'ar' ] = rate
246- rate = None
237+ audio = sum (1 for m in mode if m == "a" )
238+ video = sum (1 for m in mode if m == "v" )
239+
240+ if audio + video == 0 :
241+ raise ValueError (
242+ f"Invalid FFmpeg streaming mode argument: { mode } . Stream type not specified. Mode must contain 'v' or 'a' at least once."
243+ )
244+
245+ if read :
246+ vars = []
247+ if rate_in is not None :
248+ vars .append ("rate_in" )
249+ if rate is not None :
250+ vars .append ("rate" )
251+ if len (vars ):
252+ vars = ", " .join (vars )
253+ raise ValueError (
254+ f"Invalid argument for a read stream: { vars } . To change rate, use FFmpeg 'r' argument for video stream or 'ar' argument for audio stream."
255+ )
256+ vars = []
257+ if shape_in is not None :
258+ vars .append ("shape_in" )
259+ if shape is not None :
260+ vars .append ("shape" )
261+ if len (vars ):
262+ vars = ", " .join (vars )
263+ raise ValueError (
264+ f"Invalid argument for a read stream: { vars } . To change shape, use FFmpeg 's' argument for video frame or 'ac' for the number of audio channels."
265+ )
266+
267+ if dtype_in is not None :
268+ raise ValueError ("Invalid argument for a read stream: dtype_in." )
247269 else :
248- # auto-detect operation
249- if rate_in is None :
250- read = True
251- elif rate is None :
252- write = True
253- else :
254- filter = True
255-
256- # auto-detect type
257- if not (audio or video ):
258- if is_fg :
270+ if audio + video > 1 :
259271 raise ValueError (
260- "media type must be specified to read from an Input filtergraph "
272+ f"Too many streams specified: { mode } . A { 'write' if write else 'filter' } stream can only process one stream at a time. "
261273 )
262- elif read :
263- for url in url_fg :
264- try :
265- info = probe .streams_basic (url , entries = ("codec_type" ,))
266- except :
267- raise ValueError (f"cannot auto-detect media type of { url } " )
268- for inf in info :
269- t = inf ["codec_type" ]
270- if t == "video" and not video :
271- video = True
272- elif t == "audio" and not audio :
273- audio = True
274- if video and audio :
275- break
276-
277- else :
278- if shape_in is not None :
279- audio = len (shape_in ) < 2
280- elif shape is not None :
281- audio = len (shape ) < 2
282- else :
283- # TODO identify based on file extension
284- raise ValueError (f"cannot auto-detect media type" )
285- video = not audio
286- elif read :
287- # if audio or video is set multiple times, use avi reader
288- if audio and not video :
289- video = audio and sum ((1 for m in mode if m == "a" )) > 1
290- elif video and not audio :
291- audio = video and sum ((1 for m in mode if m == "v" )) > 1
292- elif write and is_fg :
293- ValueError ("Cannot write to a filtergraph." )
274+
275+ if write :
276+ if is_fg :
277+ ValueError ("Cannot write to a filtergraph." )
278+ if rate_in is None :
279+ raise ValueError (
280+ "Missing required argument: rate_in. A write stream must specify the rate of the input media stream."
281+ )
282+ if rate is not None :
283+ raise ValueError (
284+ "Invalid argument for a write stream: rate. To change rate, use FFmpeg 'r' argument for video stream or 'ar' argument for audio stream."
285+ )
286+ if shape is not None :
287+ raise ValueError (
288+ "Invalid argument for a read stream: shape. To change shape, use FFmpeg 's' argument for video frame or 'ac' for the number of audio channels."
289+ )
290+ else : # if filter
291+ vars = []
292+ if rate_in is None :
293+ vars .append ("rate_in" )
294+ if rate is None :
295+ vars .append ("rate" )
296+ if len (vars ):
297+ vars = ", " .join (vars )
298+ raise ValueError (
299+ f"Missing required arguments: { vars } . A filter stream must specify the rates of both the input and output media streams."
300+ )
294301
295302 try :
296- StreamClass = {
297- 1 : {
298- 0 : _streams .SimpleAudioReader ,
299- 1 : _streams .SimpleAudioWriter ,
300- 2 : _streams .SimpleAudioFilter ,
301- },
302- 2 : {
303- 0 : _streams .SimpleVideoReader ,
304- 1 : _streams .SimpleVideoWriter ,
305- 2 : _streams .SimpleVideoFilter ,
306- },
307- 3 : {
308- 0 : _streams .AviMediaReader ,
309- },
310- }[audio + 2 * video ][write + 2 * filter ]
303+ StreamClass = (
304+ {
305+ 0 : {
306+ 0 : _streams .SimpleAudioReader ,
307+ 1 : _streams .SimpleAudioWriter ,
308+ 2 : _streams .SimpleAudioFilter ,
309+ },
310+ 1 : {
311+ 0 : _streams .SimpleVideoReader ,
312+ 1 : _streams .SimpleVideoWriter ,
313+ 2 : _streams .SimpleVideoFilter ,
314+ },
315+ }[video ][write + 2 * filter ]
316+ if audio + video == 1
317+ else _streams .AviMediaReader
318+ )
311319 except :
312- raise Exception (f"Invalid/unsupported FFmpeg streaming mode: { mode } ." )
320+ raise ValueError (f"Invalid/unsupported FFmpeg streaming mode: { mode } ." )
313321
314322 if len (url_fg ) > 1 and not StreamClass .multi_read :
315- raise Exception (f'Multi-input streaming is not supported in "{ mode } " mode' )
323+ raise ValueError (f'Multi-input streaming is not supported in "{ mode } " mode' )
316324
317325 # add other info to the arguments
318326 args = (* url_fg ,) if read else (* url_fg , rate_in )
319- for k , v in (
320- ("dtype_in" , dtype_in ),
321- ("shape_in" , shape_in ),
322- ("rate" , rate ),
323- ("shape" , shape ),
324- ):
325- if v is not None :
326- kwds [k ] = v
327+ if not read :
328+ for k , v in (
329+ ("dtype_in" , dtype_in ),
330+ ("shape_in" , shape_in ),
331+ ("rate" , rate ),
332+ ("shape" , shape ),
333+ ):
334+ if v is not None :
335+ kwds [k ] = v
327336
328337 # instantiate the streaming object
329338 return StreamClass (* args , ** kwds )
0 commit comments