Get the sound intensity of a current frame


I’d like to know what is the sound intensity of a frame (if there’s sound object in the scene or audio playing in the sequencer) via bpy to create a little python “audio volume” input node for geometry node.

AFAIK there’s no api for this ? I hope I am wrong

1 Like

There is no direct way, but in this add-on is a way to do a VU-meter:

1 Like

thanks a lot @tintwotin
to anyone interested here is the function without dependencies to the rest of this fantastic plugin below :slight_smile: (except for fades)

could we perhaps have some information about what the unit represents?
the sequencer starts to draw the sound red when it hit a certain limit, so suppose i can use this to normalize, not sure what this limit is at the first place


def get_sequence_volume(frame=None):

    total = 0

    if bpy.context.scene.sequence_editor is None:
        return 0
    sequences = bpy.context.scene.sequence_editor.sequences_all
    depsgraph = bpy.context.evaluated_depsgraph_get()
    if frame is None:
          frame = bpy.context.scene.frame_current
          evaluate_volume = False
    else: evaluate_volume = True

    fps = bpy.context.scene.render.fps / bpy.context.scene.render.fps_base

    for sequence in sequences:

        if (sequence.type=="SOUND" and sequence.frame_final_start<frame and sequence.frame_final_end>frame and not sequence.mute):
            time_from = (frame - 1 - sequence.frame_start) / fps
            time_to = (frame - sequence.frame_start) / fps

            audio = sequence.sound.evaluated_get(depsgraph).factory

            chunk = audio.limit(time_from, time_to).data()
            #sometimes the chunks cannot be read properly, try to read 2 frames instead
            if (len(chunk)==0):
                time_from_temp = (frame - 2 - sequence.frame_start) / fps
                chunk = audio.limit(time_from_temp, time_to).data()
            #chunk still couldnt be read... just give up :\
            if (len(chunk)==0):
                average = 0

                cmax = abs(chunk.max())
                cmin = abs(chunk.min())
                if cmax > cmin:
                      average = cmax
                else: average = cmin

            if evaluate_volume:
                fcurve = fades.get_fade_curve(bpy.context, sequence, create=False)
                if fcurve:
                      volume = fcurve.evaluate(frame)
                else: volume = sequence.volume
                volume = sequence.volume

            total = total + (average * volume)

    return total

volume = get_sequence_volume()

Question is if this could be a built in operator so it could be used for a VU-meter and be exposed in the API?

1 Like