diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5becaf5f6..8e8077b79 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,6 +23,11 @@ Major: - Drop FFmpeg 6. - Remove ``AVError`` alias (use ``FFmpegError`` directly instead). +- Remove the `template` arg from ``OutputContainer.add_stream()``. + +Features: + +- Add ``OutputContainer.add_stream_from_template()`` by :gh-user:`WyattBlue` and :gh-user:`cdce8p`. v13.1.0 ------- diff --git a/av/container/output.pyi b/av/container/output.pyi index c318d93e5..97b67ee71 100644 --- a/av/container/output.pyi +++ b/av/container/output.pyi @@ -17,34 +17,22 @@ class OutputContainer(Container): self, codec_name: Literal["pcm_s16le", "aac", "mp3", "mp2"], rate: int | None = None, - template: None = None, options: dict[str, str] | None = None, **kwargs, ) -> AudioStream: ... @overload def add_stream( self, - codec_name: Literal["h264", "mpeg4", "png", "qtrle"], + codec_name: Literal["h264", "hevc", "mpeg4", "png", "gif", "qtrle"], rate: Fraction | int | None = None, - template: None = None, options: dict[str, str] | None = None, **kwargs, ) -> VideoStream: ... @overload def add_stream( self, - codec_name: None = None, + codec_name: str, rate: Fraction | int | None = None, - template: _StreamT | None = None, - options: dict[str, str] | None = None, - **kwargs, - ) -> _StreamT: ... - @overload - def add_stream( - self, - codec_name: str | None = None, - rate: Fraction | int | None = None, - template: Stream | None = None, options: dict[str, str] | None = None, **kwargs, ) -> Stream: ... diff --git a/av/container/output.pyx b/av/container/output.pyx index f80c6e55e..3e4c9dbb4 100644 --- a/av/container/output.pyx +++ b/av/container/output.pyx @@ -43,33 +43,28 @@ cdef class OutputContainer(Container): with nogil: lib.av_packet_free(&self.packet_ptr) - def add_stream(self, codec_name=None, object rate=None, Stream template=None, options=None, **kwargs): + def add_stream(self, codec_name, rate=None, dict options=None, **kwargs): """add_stream(codec_name, rate=None) - Creates a new stream from a codec name or a template, and returns it. + Creates a new stream from a codec name and returns it. :param codec_name: The name of a codec. - :type codec_name: str | Codec | None - :param template: Copy codec from another :class:`~av.stream.Stream` instance. - :type template: :class:`~av.stream.Stream` | None + :type codec_name: str | Codec :param dict options: Stream options. :param \\**kwargs: Set attributes for the stream. :rtype: The new :class:`~av.stream.Stream`. """ - if (codec_name is None and template is None) or (codec_name is not None and template is not None): - raise ValueError("needs one of codec_name or template") - cdef const lib.AVCodec *codec cdef Codec codec_obj - if codec_name is not None: - codec_obj = codec_name if isinstance(codec_name, Codec) else Codec(codec_name, "w") + if isinstance(codec_name, Codec): + if codec_name.mode != "w": + raise ValueError("codec_name must be an encoder.") + codec_obj = codec_name else: - if not template.codec_context: - raise ValueError("template has no codec context") - codec_obj = template.codec_context.codec + codec_obj = Codec(codec_name, "w") codec = codec_obj.ptr # Assert that this format supports the requested codec. @@ -82,14 +77,8 @@ cdef class OutputContainer(Container): cdef lib.AVStream *stream = lib.avformat_new_stream(self.ptr, codec) cdef lib.AVCodecContext *codec_context = lib.avcodec_alloc_context3(codec) - # Copy from the template. - if template is not None: - err_check(lib.avcodec_parameters_to_context(codec_context, template.ptr.codecpar)) - # Reset the codec tag assuming we are remuxing. - codec_context.codec_tag = 0 - # Now lets set some more sane video defaults - elif codec.type == lib.AVMEDIA_TYPE_VIDEO: + if codec.type == lib.AVMEDIA_TYPE_VIDEO: codec_context.pix_fmt = lib.AV_PIX_FMT_YUV420P codec_context.width = kwargs.pop("width", 640) codec_context.height = kwargs.pop("height", 480)