@@ -217,6 +217,17 @@ def as_filtergraph_object(filter_specs):
217217 return as_filtergraph (filter_specs )
218218
219219
220+ def _shift_labels (obj , label_type , args ):
221+ if _is_label (args ):
222+ return obj .add_labels (label_type , args )
223+
224+ if all (_is_label (arg ) for arg in args ):
225+ return obj .add_labels (label_type , [arg for arg in args ])
226+
227+ assert len (args ) == 2 and _is_label (args [0 ])
228+ return obj .add_labels (label_type , {args [1 ]: args [0 ]})
229+
230+
220231###################################################################################################
221232
222233# FILTER TOOLS
@@ -613,26 +624,25 @@ def _channelsplit():
613624 else inc ()
614625 )
615626
616- def add_labels (self , input_labels = None , output_labels = None ):
627+ def add_labels (self , pad_type , labels ):
617628 """turn into filtergraph and add labels
618629
619- :param input_labels: input pad labels keyed by pad index, defaults to None
620- :type input_labels: dict(int:str), optional
621- :param output_labels: output pad labels keyed by pad index, defaults to None
622- :type output_labels: dict(int:str), optional
630+ :param pad_type: filter pad type
631+ :type pad_type: 'dst'|'src'
632+ :param labels: pad label(s) and optionally pad id
633+ :type labels: str|seq(str)| dict(int:str), optional
623634 """
624635
625636 fg = Graph ([[self ]])
626- if input_labels is not None :
627- for pad , label in input_labels .items ():
628- if label [0 ] == "[" and label [- 1 ] == "]" :
629- label = label [1 :- 1 ]
630- fg .add_label (label , dst = (0 , 0 , pad ))
631- if output_labels is not None :
632- for pad , label in output_labels .items ():
633- if label [0 ] == "[" and label [- 1 ] == "]" :
634- label = label [1 :- 1 ]
635- fg .add_label (label , src = (0 , 0 , pad ))
637+ if labels is not None :
638+ if isinstance (labels , str ):
639+ fg .add_label (labels , ** {pad_type : (0 , 0 , 0 )})
640+ elif isinstance (labels , dict ):
641+ for pad , label in labels .items ():
642+ fg .add_label (label , ** {pad_type : fg ._resolve_index (pad )})
643+ else :
644+ for pad , label in enumerate (labels ):
645+ fg .add_label (label , ** {pad_type : (0 , 0 , pad )})
636646 return fg
637647
638648 def apply (self , options , filter_id = None ):
@@ -755,6 +765,14 @@ def __ror__(self, other):
755765 def __rshift__ (self , other ):
756766 """self >> other | self >> (index, other)"""
757767
768+ # try labeling first
769+ try :
770+ return _shift_labels (self , "src" , other )
771+ except FFmpegioError :
772+ raise
773+ except :
774+ pass
775+
758776 # resolve the index
759777 if type (other ) == tuple :
760778 if len (other ) > 2 :
@@ -768,13 +786,6 @@ def __rshift__(self, other):
768786
769787 index = self ._resolve_index (False , index )
770788
771- # if label
772- if _is_label (other ):
773- if other_index is None :
774- return self .add_labels (output_labels = {index : other })
775- else :
776- raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
777-
778789 # if other is Filter object, do add operation
779790 try :
780791 other = as_filtergraph_object (other )
@@ -798,6 +809,14 @@ def __rshift__(self, other):
798809 def __rrshift__ (self , other ):
799810 """other >> self, (other, index) >> self : attach input label or filter"""
800811
812+ # try to label first
813+ try :
814+ return _shift_labels (self , "dst" , other )
815+ except FFmpegioError :
816+ raise
817+ except :
818+ pass
819+
801820 # resolve the index
802821 if type (other ) == tuple :
803822 if len (other ) > 2 :
@@ -814,7 +833,7 @@ def __rrshift__(self, other):
814833 # if label
815834 if _is_label (other ):
816835 if other_index is None :
817- return self .add_labels (input_labels = {index : other })
836+ return self .add_labels ("dst" , {index : other })
818837 else :
819838 raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
820839
@@ -980,6 +999,15 @@ def __ror__(self, other):
980999 return Graph ([other , self ]) if n and m else self if n else other
9811000
9821001 def __rshift__ (self , other ):
1002+ """self >> other | self >> (index, other) | self >> (index, other_index, other)"""
1003+
1004+ # try to label first
1005+ try :
1006+ return _shift_labels (self , "src" , other )
1007+ except FFmpegioError :
1008+ raise
1009+ except :
1010+ pass
9831011
9841012 if type (other ) == tuple :
9851013 if len (other ) > 2 :
@@ -1010,15 +1038,6 @@ def __rshift__(self, other):
10101038
10111039 index = self ._resolve_index (False , index )
10121040
1013- # if label
1014- if _is_label (other ):
1015- if other_index is None :
1016- fg = Graph ([self ])
1017- fg .add_label (other [1 :- 1 ], src = (0 , * index ))
1018- return fg
1019- else :
1020- raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
1021-
10221041 # if other is Filter object, do add operation
10231042 try :
10241043 other = as_filtergraph_object (other )
@@ -1041,6 +1060,14 @@ def __rshift__(self, other):
10411060 def __rrshift__ (self , other ):
10421061 """other >> self, (other, index) >> self : attach input label or filter"""
10431062
1063+ # try to label first
1064+ try :
1065+ return _shift_labels (self , "dst" , other )
1066+ except FFmpegioError :
1067+ raise
1068+ except :
1069+ pass
1070+
10441071 # resolve the index
10451072 if type (other ) == tuple :
10461073 if len (other ) > 2 :
@@ -1065,15 +1092,6 @@ def __rrshift__(self, other):
10651092
10661093 index = self ._resolve_index (True , index )
10671094
1068- # if label
1069- if _is_label (other ):
1070- if other_index is None :
1071- fg = Graph ([self ])
1072- fg .add_label (other [1 :- 1 ], dst = (0 , * index ))
1073- return fg
1074- else :
1075- raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
1076-
10771095 # if other is Filter object, do add operation
10781096 try :
10791097 other = as_filtergraph_object (other )
@@ -1230,6 +1248,30 @@ def validate_output_index(self, pos, pad_pos):
12301248 if pad_pos < 0 or pad_pos >= (n - 1 if pos < len (self .data ) - 1 else n ):
12311249 raise Chain .Error (f"invliad output pad position #{ pos } for { self [pos ]} ." )
12321250
1251+ def add_labels (self , pad_type , labels ):
1252+ """turn into filtergraph and add labels
1253+
1254+ :param input_labels: input pad labels keyed by pad index, defaults to None
1255+ :type input_labels: dict(int:str), optional
1256+ :param output_labels: output pad labels keyed by pad index, defaults to None
1257+ :type output_labels: dict(int:str), optional
1258+ """
1259+
1260+ fg = Graph ([self ])
1261+ is_input = pad_type == "dst"
1262+ if isinstance (labels , str ):
1263+ pad = fg ._resolve_index (is_input , None )
1264+ fg .add_label (labels , ** {pad_type : pad })
1265+ elif isinstance (labels , dict ):
1266+ for pad , label in labels .items ():
1267+ pad = fg ._resolve_index (is_input , pad )
1268+ fg .add_label (label , ** {pad_type : pad })
1269+ else :
1270+ for pad , label in enumerate (labels ):
1271+ pad = fg ._resolve_index (is_input , pad )
1272+ fg .add_label (label , ** {pad_type : pad })
1273+ return fg
1274+
12331275
12341276####################################################################################
12351277
@@ -1495,6 +1537,14 @@ def __ror__(self, other):
14951537 def __rshift__ (self , other ):
14961538 """self >> other | self >> (index, other) | self >> (index, other_index, other)"""
14971539
1540+ # try to label first
1541+ try :
1542+ return _shift_labels (self , "src" , other )
1543+ except FFmpegioError :
1544+ raise
1545+ except :
1546+ pass
1547+
14981548 # resolve the index
14991549 if type (other ) == tuple :
15001550 if len (other ) > 2 :
@@ -1519,15 +1569,6 @@ def __rshift__(self, other):
15191569
15201570 index = self ._resolve_index (False , index )
15211571
1522- # if label
1523- if _is_label (other ):
1524- if other_index is None :
1525- fg = Graph (self ) # copy
1526- fg .add_label (other [1 :- 1 ], src = index )
1527- return fg
1528- else :
1529- raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
1530-
15311572 # if other is Filter object, do add operation
15321573 try :
15331574 other = as_filtergraph_object (other )
@@ -1539,6 +1580,14 @@ def __rshift__(self, other):
15391580 def __rrshift__ (self , other ):
15401581 """other >> self, (other, index) >> self, (other, other_index, index) >> self : attach input label or filter"""
15411582
1583+ # try to label first
1584+ try :
1585+ return _shift_labels (self , "dst" , other )
1586+ except FFmpegioError :
1587+ raise
1588+ except :
1589+ pass
1590+
15421591 # resolve the index
15431592 if type (other ) == tuple :
15441593 if len (other ) > 2 :
@@ -1563,15 +1612,6 @@ def __rrshift__(self, other):
15631612
15641613 index = self ._resolve_index (True , index )
15651614
1566- # if label
1567- if _is_label (other ):
1568- if other_index is None :
1569- fg = Graph (self ) # copy
1570- fg .add_label (other [1 :- 1 ], dst = index )
1571- return fg
1572- else :
1573- raise FiltergraphInvalidIndex ("index cannot be assigned to a label" )
1574-
15751615 # if other is Filter object, do add operation
15761616 try :
15771617 other = as_filtergraph (other )
@@ -1952,7 +1992,7 @@ def link(self, dst, src, label=None, preserve_src_label=False, force=False):
19521992 def add_label (self , label , dst = None , src = None , force = None ):
19531993 """label a filter pad
19541994
1955- :param label: name of the new label
1995+ :param label: name of the new label. Square brackets are optional.
19561996 :type label: str
19571997 :param dst: input filter pad index or a sequence of pads, defaults to None
19581998 :type dst: tuple(int,int,int) | seq(tuple(int,int,int)), optional
@@ -1972,6 +2012,9 @@ def add_label(self, label, dst=None, src=None, force=None):
19722012
19732013 """
19742014
2015+ if label [0 ] == "[" and label [- 1 ] == "]" :
2016+ label = label [1 :- 1 ]
2017+
19752018 GraphLinks .validate_label (
19762019 label , named_only = True , no_stream_spec = src is not None
19772020 )
@@ -2428,6 +2471,30 @@ def rattach(self, left, right_on=None, left_on=None):
24282471 right_on = self ._resolve_index (True , right_on )
24292472 return left .connect (self , [left_on ], [right_on ], chain_siso = True )
24302473
2474+ def add_labels (self , pad_type , labels ):
2475+ """turn into filtergraph and add labels
2476+
2477+ :param input_labels: input pad labels keyed by pad index, defaults to None
2478+ :type input_labels: dict(int:str), optional
2479+ :param output_labels: output pad labels keyed by pad index, defaults to None
2480+ :type output_labels: dict(int:str), optional
2481+ """
2482+
2483+ fg = Graph (self )
2484+ is_input = pad_type == "dst"
2485+ if isinstance (labels , str ):
2486+ pad = fg ._resolve_index (is_input , None )
2487+ fg .add_label (labels , ** {pad_type : pad })
2488+ elif isinstance (labels , dict ):
2489+ for pad , label in labels .items ():
2490+ pad = fg ._resolve_index (is_input , None )
2491+ fg .add_label (label , ** {pad_type : pad })
2492+ else :
2493+ for label in labels :
2494+ pad = fg ._resolve_index (is_input , None )
2495+ fg .add_label (label , ** {pad_type : pad })
2496+ return fg
2497+
24312498 @contextmanager
24322499 def as_script_file (self ):
24332500 """return script file containing the filtergraph description
0 commit comments