From 14dbb924e19ee5b5b943edb724c24a93c4dc1a2f Mon Sep 17 00:00:00 2001 From: bymyself Date: Sat, 8 Aug 2026 20:28:57 -0700 Subject: [PATCH] Use PyAV's own predicate instead of querying supported codecs OutputContainer.supported_codecs only keeps codecs for which avformat_query_codec returns 1, while add_stream_from_template rejects only a falsy result. Muxers that implement neither a query_codec callback nor a codec_tag table return AVERROR_PATCHWELCOME, so they accept a stream copy that supported_codecs reports as impossible: an h264 mpegts source saved with format=auto was fully re-encoded and silently rehoused in mp4. Attempt the copy and let PyAV answer instead. All streams are added before the first packet is muxed, so a stream the destination rejects is caught before anything is written. Handling it per stream also means a subtitle track the destination cannot store is dropped on its own rather than diverting the video alongside it into a needless re-encode. Log the whole-file re-encode at warning, since it is lossy and discards the extra audio and subtitle streams the transcode path does not carry. --- comfy_api/latest/_input_impl/video_types.py | 38 +++++++++------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/comfy_api/latest/_input_impl/video_types.py b/comfy_api/latest/_input_impl/video_types.py index d35318c7a..b08a6fc9a 100644 --- a/comfy_api/latest/_input_impl/video_types.py +++ b/comfy_api/latest/_input_impl/video_types.py @@ -100,17 +100,6 @@ def write_output_metadata(container: InputContainer, output, metadata: dict | No output.metadata[key] = value if isinstance(value, str) else json.dumps(value) -def unsupported_remux_codecs(streams, output_container) -> list[str]: - supported = output_container.supported_codecs - return [ - stream.codec_context.name - for stream in streams - if isinstance(stream, (av.VideoStream, av.AudioStream, SubtitleStream)) - and stream.codec_context is not None - and stream.codec_context.name not in supported - ] - - def mp4_output_open_kwargs(path: str | io.BytesIO, format: VideoContainer, codec: VideoCodec) -> dict: if format != VideoContainer.AUTO and format != VideoContainer.MP4: raise ValueError("Only MP4 format is supported for now") @@ -521,15 +510,6 @@ class VideoFromFile(VideoInput): ) -> bool: streams = container.streams with av.open(path, **open_kwargs) as output_container: - unsupported = unsupported_remux_codecs(streams, output_container) - if unsupported: - logging.info( - "Cannot copy %s into a %s container; re-encoding instead.", - ", ".join(sorted(set(unsupported))), - output_container.format.name, - ) - return False - # Add metadata before writing any streams write_output_metadata(container, output_container, metadata) @@ -540,7 +520,23 @@ class VideoFromFile(VideoInput): if stream.codec_context is None: logging.warning("Skipping %s stream %d with unsupported codec", stream.type, stream.index) continue - out_stream = output_container.add_stream_from_template(template=stream, opaque=True) + try: + out_stream = output_container.add_stream_from_template(template=stream, opaque=True) + except ValueError: + codec_name = stream.codec_context.name + format_name = output_container.format.name + if isinstance(stream, SubtitleStream): + logging.warning( + "Dropping %s subtitle stream %d: the %s container cannot store it.", + codec_name, stream.index, format_name, + ) + continue + logging.warning( + "The %s container cannot store %s, so the whole file is being re-encoded to H.264/AAC. " + "Any additional audio or subtitle streams will be dropped.", + format_name, codec_name, + ) + return False stream_map[stream] = out_stream # Write packets to the new container