@@ -635,12 +635,15 @@ def validate_concat_operation(op: Dict[str, Any]) -> Dict[str, Any]:
635635def validate_transcode_operation (op : Dict [str , Any ]) -> Dict [str , Any ]:
636636 """Validate transcode operation with enhanced security checks."""
637637 validated = {"type" : "transcode" }
638-
638+
639639 # Allowed video codecs
640- ALLOWED_VIDEO_CODECS = {'h264' , 'h265' , 'hevc' , 'vp8' , 'vp9' , 'av1' , 'libx264' , 'libx265' , 'copy' }
641- ALLOWED_AUDIO_CODECS = {'aac' , 'mp3' , 'opus' , 'vorbis' , 'ac3' , 'libfdk_aac' , 'copy' }
640+ ALLOWED_VIDEO_CODECS = {'h264' , 'h265' , 'hevc' , 'vp8' , 'vp9' , 'av1' , 'libx264' , 'libx265' , 'copy' , 'prores' , 'dnxhd' }
641+ ALLOWED_AUDIO_CODECS = {'aac' , 'mp3' , 'opus' , 'vorbis' , 'ac3' , 'eac3' , ' libfdk_aac' , 'flac' , 'pcm_s16le' , 'pcm_s24le ' , 'copy' }
642642 ALLOWED_PRESETS = {'ultrafast' , 'superfast' , 'veryfast' , 'faster' , 'fast' , 'medium' , 'slow' , 'slower' , 'veryslow' }
643-
643+ ALLOWED_PROFILES = {'baseline' , 'main' , 'high' , 'high10' , 'high422' , 'high444' }
644+ ALLOWED_PIXEL_FORMATS = {'yuv420p' , 'yuv422p' , 'yuv444p' , 'yuv420p10le' , 'yuv422p10le' , 'rgb24' , 'rgba' }
645+ ALLOWED_HW_ACCEL = {'auto' , 'none' , 'nvenc' , 'qsv' , 'vaapi' , 'videotoolbox' }
646+
644647 # Validate video codec
645648 if "video_codec" in op :
646649 codec = op ["video_codec" ]
@@ -649,7 +652,7 @@ def validate_transcode_operation(op: Dict[str, Any]) -> Dict[str, Any]:
649652 if codec not in ALLOWED_VIDEO_CODECS :
650653 raise ValueError (f"Invalid video codec: { codec } " )
651654 validated ["video_codec" ] = codec
652-
655+
653656 # Validate audio codec
654657 if "audio_codec" in op :
655658 codec = op ["audio_codec" ]
@@ -658,7 +661,7 @@ def validate_transcode_operation(op: Dict[str, Any]) -> Dict[str, Any]:
658661 if codec not in ALLOWED_AUDIO_CODECS :
659662 raise ValueError (f"Invalid audio codec: { codec } " )
660663 validated ["audio_codec" ] = codec
661-
664+
662665 # Validate preset
663666 if "preset" in op :
664667 preset = op ["preset" ]
@@ -667,21 +670,48 @@ def validate_transcode_operation(op: Dict[str, Any]) -> Dict[str, Any]:
667670 if preset not in ALLOWED_PRESETS :
668671 raise ValueError (f"Invalid preset: { preset } " )
669672 validated ["preset" ] = preset
670-
673+
674+ # Validate profile (for H.264/H.265)
675+ if "profile" in op :
676+ profile = op ["profile" ]
677+ if not isinstance (profile , str ):
678+ raise ValueError ("Profile must be a string" )
679+ if profile not in ALLOWED_PROFILES :
680+ raise ValueError (f"Invalid profile: { profile } " )
681+ validated ["profile" ] = profile
682+
683+ # Validate pixel format
684+ if "pixel_format" in op or "pix_fmt" in op :
685+ pix_fmt = op .get ("pixel_format" ) or op .get ("pix_fmt" )
686+ if pix_fmt not in ALLOWED_PIXEL_FORMATS :
687+ raise ValueError (f"Invalid pixel format: { pix_fmt } " )
688+ validated ["pixel_format" ] = pix_fmt
689+
690+ # Validate hardware acceleration
691+ if "hardware_acceleration" in op or "hw_accel" in op :
692+ hw = op .get ("hardware_acceleration" ) or op .get ("hw_accel" )
693+ if hw not in ALLOWED_HW_ACCEL :
694+ raise ValueError (f"Invalid hardware acceleration: { hw } " )
695+ validated ["hardware_acceleration" ] = hw
696+
671697 # Validate bitrates
672698 if "video_bitrate" in op :
673699 validated ["video_bitrate" ] = validate_bitrate (op ["video_bitrate" ])
674700 if "audio_bitrate" in op :
675701 validated ["audio_bitrate" ] = validate_bitrate (op ["audio_bitrate" ])
676-
702+ if "max_bitrate" in op :
703+ validated ["max_bitrate" ] = validate_bitrate (op ["max_bitrate" ])
704+ if "buffer_size" in op :
705+ validated ["buffer_size" ] = validate_bitrate (op ["buffer_size" ])
706+
677707 # Validate resolution
678708 if "width" in op or "height" in op :
679709 width = op .get ("width" )
680710 height = op .get ("height" )
681711 validated_resolution = validate_resolution (width , height )
682712 if validated_resolution :
683713 validated .update (validated_resolution )
684-
714+
685715 # Validate frame rate
686716 if "fps" in op :
687717 fps = op ["fps" ]
@@ -691,7 +721,7 @@ def validate_transcode_operation(op: Dict[str, Any]) -> Dict[str, Any]:
691721 validated ["fps" ] = float (fps )
692722 else :
693723 raise ValueError ("FPS must be a number" )
694-
724+
695725 # Validate CRF
696726 if "crf" in op :
697727 crf = op ["crf" ]
@@ -701,7 +731,46 @@ def validate_transcode_operation(op: Dict[str, Any]) -> Dict[str, Any]:
701731 validated ["crf" ] = int (crf )
702732 else :
703733 raise ValueError ("CRF must be a number" )
704-
734+
735+ # Validate GOP size (keyframe interval)
736+ if "gop_size" in op or "keyint" in op :
737+ gop = op .get ("gop_size" ) or op .get ("keyint" )
738+ if isinstance (gop , int ):
739+ if gop < 1 or gop > 600 :
740+ raise ValueError ("GOP size out of valid range (1-600)" )
741+ validated ["gop_size" ] = gop
742+ else :
743+ raise ValueError ("GOP size must be an integer" )
744+
745+ # Validate B-frames
746+ if "b_frames" in op or "bframes" in op :
747+ bf = op .get ("b_frames" ) or op .get ("bframes" )
748+ if isinstance (bf , int ):
749+ if bf < 0 or bf > 16 :
750+ raise ValueError ("B-frames out of valid range (0-16)" )
751+ validated ["b_frames" ] = bf
752+ else :
753+ raise ValueError ("B-frames must be an integer" )
754+
755+ # Validate two-pass encoding
756+ if "two_pass" in op :
757+ validated ["two_pass" ] = bool (op ["two_pass" ])
758+
759+ # Validate audio sample rate
760+ if "audio_sample_rate" in op :
761+ sr = op ["audio_sample_rate" ]
762+ allowed_rates = [8000 , 11025 , 16000 , 22050 , 32000 , 44100 , 48000 , 96000 ]
763+ if sr not in allowed_rates :
764+ raise ValueError (f"Invalid audio sample rate: { sr } " )
765+ validated ["audio_sample_rate" ] = sr
766+
767+ # Validate audio channels
768+ if "audio_channels" in op :
769+ channels = op ["audio_channels" ]
770+ if channels not in [1 , 2 , 6 , 8 ]:
771+ raise ValueError ("Audio channels must be 1, 2, 6, or 8" )
772+ validated ["audio_channels" ] = channels
773+
705774 return validated
706775
707776
0 commit comments