0
$\begingroup$

Have an animation (made from geometry nodes) along with the script below. Everything works fine in viewport, the animation plays and the test.wav plays when it should. During render there is no sound, period. If i 'render audio' i can hear the test.wav (at a much faster rate) while the render is taking place, but the saved rendered file has no sound, but is correct length. If i render the animation as a video using FFmpegvideo and (different Audio Codec's), the video is fine, but no audio. If i take that video clip into an audio editor (Reaper) there is no sound wave in the file, only a left and right channel, but solid lines. Ive tried this in both Eevee and Cycles and im using Blender 3.0.

import bpy
import aud

oldTEST = 00.0
aPath = r"N:\path_to_audio\test.wav"

device = aud.Device()
sound = aud.Sound(aPath)
sound_buffered = aud.Sound.cache(sound)

def frame_change_post_def(scene, context):
    global oldTEST, device, sound_buffered
    
    obj = bpy.context.object.evaluated_get(bpy.context.evaluated_depsgraph_get()).data
    newTEST = obj.attributes['TEST_Count'].data[0].value
    
    if newTEST != oldTEST:
        handle = device.play(sound_buffered) 
        
    
    oldTEST = newTEST

bpy.app.handlers.frame_change_post.clear()
bpy.app.handlers.frame_change_post.append(frame_change_post_def)
$\endgroup$
8
  • 1
    $\begingroup$ if u provide blend file, we could check it out. Else you have to wait for someone who already tried this (which i think are only a few people)... $\endgroup$
    – Chris
    Commented Jan 13, 2022 at 10:28
  • $\begingroup$ Thanks Chris, will try and put an example project together (rather not post real project) when i get home. $\endgroup$ Commented Jan 13, 2022 at 16:08
  • 1
    $\begingroup$ IIRC You either need to add a speaker to the scene or create a sound strip in the VSE to contain the wav file for it to show up in the final render. And, of course, you need to render to a format that Blender can convert wav audio to. $\endgroup$ Commented Jan 13, 2022 at 17:52
  • $\begingroup$ Ill test when i get home, question... The script i posted will "trigger" the sound at certain times during the animation. When you say, adding a speaker or wave clip to VSE, will they have to be key framed or will i still be able to control the sound with my script ? $\endgroup$ Commented Jan 13, 2022 at 19:02
  • 1
    $\begingroup$ Yes, discovered that and when you add a speaker it adds a new strip to the NLA editor. Where ever you are in the time line when you add the speaker, it will add the speaker to that frame. Tested a 'render audio' with speaker added and it will play the sound at that key frame. Going to try and move that NLA entry around with python and try and control it with the script. $\endgroup$ Commented Jan 14, 2022 at 0:05

2 Answers 2

0
$\begingroup$

Still have not found a solution to original issue, but managed to create a work around using a Speaker object as @Marty-Fouts suggested and then moving its start frame as needed with the script. Still can not use the 'render audio' option (creates empty audio file), but can render audio using FFmpegvideo and selecting 'Video Encoder = No Video' and AAC as audio (during testing, render time was about 1 sec per-frame).

During viewport, if the script uses 'bpy.app.handlers.frame_change_pre.append' everything works fine, but during render no sound changes via the script. During rendering if the script uses 'bpy.app.handlers.render_write.append' it works, but if calling both 'render_write.append' and 'frame_change_pre.append' at the same time it will crash blender (most of the time) and if enabling 'Lock Interface', the script sound will not work. So i "toggling" between the two with the 'RENDER_ON' variable at the top of the script.

With that said, i can get everything work with little effort, but the original issue still stands. Any other suggestions would be great.

Link for bpy.app.handlers

Setup: scene with a geometry node (named: GEO_OBJ_TEST) sending output (attributes name: testSoundTrigger), a speaker (named: Speaker) and the following script.

import bpy
from bpy.app import handlers


RENDER_ON  = 0
DEBUG = 1

GEO_OBJ_NAME = 'GEO_OBJ_TEST'
GEO_ATT_NAME = 'testSoundTrigger'

SPEAKER_NAME = 'Speaker'

NLA_TRACK_NAME = 'SoundTrack'
NLA_STRIP_NAME = 'NLA Strip'
NLA_STRIP_LEN = 20


oldChr = 00.0

def frame_change_def(scene):
    global oldChr, NLA_STRIP_LEN
    
    GEO_OBJ = scene.objects[GEO_OBJ_NAME]
    GEO_ATT = GEO_OBJ.evaluated_get(bpy.context.evaluated_depsgraph_get()).data
    
    speaker = scene.objects[SPEAKER_NAME]
    SoundStrip = speaker.animation_data.nla_tracks[NLA_TRACK_NAME].strips[NLA_STRIP_NAME]
 
    newChr = oldChr 
    
    try:
        newChr = GEO_ATT.attributes[GEO_ATT_NAME].data[0].value
    except KeyError: 
        pass
    finally: 
        
        if newChr != oldChr:  
            
            currentFrame = scene.frame_current
            
            if DEBUG: print(" " * 4, "FRAME    ",  currentFrame)
            if DEBUG: print(" " * 4, "GEO INFO ",  newChr)
            if DEBUG: print(" " * 4, "BEFORE   ", SoundStrip.frame_start, SoundStrip.frame_end) 
                
            ssStart = currentFrame 
            ssEnd = ssStart + NLA_STRIP_LEN
            SoundStrip.frame_start = ssStart
            SoundStrip.frame_end = ssEnd 
                     
            if DEBUG: print(" " * 4, "AFTER    ", SoundStrip.frame_start, SoundStrip.frame_end)
            if DEBUG: print(" ")
            
        oldChr = newChr


frame_handlers = [getattr(handlers, name)
        for name in dir(handlers) if name.startswith("render_")]

def clear_handlers():
    for  handler in frame_handlers:
        handler.clear()


clear_handlers()
bpy.app.handlers.frame_change_pre.clear()

print("SOUND SCRIPT ON - ", bpy.path.basename(bpy.context.blend_data.filepath))

if RENDER_ON:
    bpy.app.handlers.render_write.append(frame_change_def)
    print("RENDER ON")
else:
    bpy.app.handlers.frame_change_pre.append(frame_change_def )
    print("RENDER OFF")

Heres a link to the .blend file from the project in the video below (which the idea in this thread spawned from, it has a script which functions just like the one im posting here): https://github.com/SidewaysUpJoe/blender-Geometry-Node-typing

And heres a video of everything in action (along with an explanation of using a script like this with geometry nodes). https://www.youtube.com/watch?v=pudfbq8S9fE

Hope someone finds this useful.

$\endgroup$
0
$\begingroup$

The solution comes from Richard Antalik, at developer.blender.org

Enable Sequencer in Output Properties > Post Processing panel.

In Blender 3.0 the Output Properties (tab) is where you define the size of your output, where to output your file to, encoding for video and audio, etc. You will also find in the same tab the Post Processing panel with compositing and sequencer check boxes. Put a check on the Sequencer.

$\endgroup$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .