1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
# av/filter/loudnorm.pyx
cimport libav as lib
from cpython.bytes cimport PyBytes_FromString
from libc.stdlib cimport free
from av.audio.codeccontext cimport AudioCodecContext
from av.audio.stream cimport AudioStream
from av.container.core cimport Container
from av.stream cimport Stream
from av.logging import get_level, set_level
cdef extern from "libavcodec/avcodec.h":
ctypedef struct AVCodecContext:
pass
cdef extern from "libavformat/avformat.h":
ctypedef struct AVFormatContext:
pass
cdef extern from "loudnorm_impl.h":
char* loudnorm_get_stats(
AVFormatContext* fmt_ctx,
int audio_stream_index,
const char* loudnorm_args
) nogil
cpdef bytes stats(str loudnorm_args, AudioStream stream):
"""
Get loudnorm statistics for an audio stream.
Args:
loudnorm_args (str): Arguments for the loudnorm filter (e.g. "i=-24.0:lra=7.0:tp=-2.0")
stream (AudioStream): Input audio stream to analyze
Returns:
bytes: JSON string containing the loudnorm statistics
"""
if "print_format=json" not in loudnorm_args:
loudnorm_args = loudnorm_args + ":print_format=json"
cdef Container container = stream.container
cdef AVFormatContext* format_ptr = container.ptr
container.ptr = NULL # Prevent double-free
cdef int stream_index = stream.index
cdef bytes py_args = loudnorm_args.encode("utf-8")
cdef const char* c_args = py_args
cdef char* result
# Save log level since C function overwrite it.
level = get_level()
with nogil:
result = loudnorm_get_stats(format_ptr, stream_index, c_args)
if result == NULL:
raise RuntimeError("Failed to get loudnorm stats")
py_result = result[:] # Make a copy of the string
free(result) # Free the C string
set_level(level)
return py_result
|