Is it possible to play an AudioStreamPlayer for x seconds without a timer?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Godont

I have an AudioStreamPlayer which I sometimes wish to play for only x seconds.

I know I can set up a timer, and stop the player once the timer is finished, but is there any built in way to do this without having to go through that rigamorole? Something along the lines of

$Player.play(duration_seconds)

? I may want to do this often and don’t want to create too many timers.

Also, I realize I could try to cut the .wav file in a separate software and use the cut version, but this doesn’t always work. For example, the Metal medieval construction sound file from this site, when cut in VLC media player, leaves out the initial strike sound and so trying to cut the file from the beginning to x seconds doesn’t work as a solution with that software (I’m not sure if better options exist, but google seems to suggest VLC in top searches).

Maybe if you use _process(delta) you can use the delta variant to stop it?
Edit:
Looking up the AudioStreamPlayer.get_playback_position() method could help

Lazarwolfe | 2021-02-03 18:21

yield(get_tree().create_timer(5.0), "timeout") will generate a 5 second wait time before the function which calls it continues (automatically).

PercentageProud | 2021-02-05 04:01

Sound buffering can mess with any timer implementation.
Sync the gameplay with audio and music — Godot Engine (stable) documentation in English

First you have godot buffer, then OS buffering may be involved (Hello Linux/Pulse audio).

The Sound server may be on a separate thread. Your GDScript timer may be halted while it keeps playing file to some buffer.(not sure about what try asking engine devs)

If you need to play 5 seconds of larger sound, cut 5 seconds in an audio editor and save in a separate file.

yrtv | 2021-02-05 15:21

:bust_in_silhouette: Reply From: yrtv

Option 1:Use Player.seek (float to_position) before Player.play(). For full AudioStreamPlayer API see AudioStreamPlayer — Godot Engine (stable) documentation in English

Player.play ( float from_position=0.0 ) do exist but fails on my android device so i advice first seek then play.

Option 2: Cut out needed part in https://www.audacityteam.org

Doesn’t the seek function only allow you to specify the start time, and not the stop?

Godont | 2021-02-03 19:35

So option 1 here unfortunately doesn’t work because it only lets me choose a starting time, and not a stopping time, for my clip (unless I misunderstood something).

I did download audacity (option 2) and used it to create my clips (thanks for the recommendation!). It is a much better software for this than VLC, but I do think it would be useful for the devs to add an option to “play_until” on audio stream players (if they have the time).

Godont | 2021-02-09 16:27

:bust_in_silhouette: Reply From: PercentageProud

I use animations or timers. I’m already using them to handle timing for the audio player. I use the same animation that fades the screen out to fade out bgm audio, the same anim that spins my bullets plays the impact sfx on the last frame, etc. If there’s no relevant animation, I use a timer.

It seems like you might be using the same audio file, just cutting it short for one use case, which would be a perfect time to just make a shortened copy of the audio file. I use VLC, and can say it’s more a media player than a media editor. I didn’t even know it had such functionality. Audacity would likely not cause the issue you got from VLC.

If it is in fact multiple different audio files all needing to be cut to a specific duration depending on circumstances that vary in-game, then I believe you will want to either use Timers or Animations.

I’m no expert, there may yet be a better solution or at least a more efficient one.

:bust_in_silhouette: Reply From: attunemm

You can use a Tween to change the AudioStreamPlayer dB, so that the player is silent after a set amount of time:

var tw = Tween.new()
var asp = AudioStreamPlayer.new()
func _ready():
# add an AudioStreamPlayer and Tween to scene
add_child(asp)
add_child(tw)
tw.connect("tween_all_completed",self,'_on_tween_all_completed')
func play_for(start_t = 0, dur = 1.5): 
# start_t delays the playing start; dur is how long to play after start

var start_dB = 0
var final_dB = -60 # adjust this as needed to silence or just lower volume after duration

tw.remove_all() # remove all previous tween settings; reset_all() didn't work
asp.set_volume_db(start_dB)
var transition_duration = 0.1
var transition_type = Tween.TRANS_QUART 
# avoid popping by fading in at start_t
tw.interpolate_property(asp,'volume_dB',-60,start_dB,0.05,transition_type,Tween.EASE_IN,start_t) 
# fade out so sound ends after dur seconds
tw.interpolate_property(asp, "volume_db", start_dB, final_dB, transition_duration, transition_type, Tween.EASE_IN, start_t + dur - transition_duration) 
# delay the start of playing;  playing from the start of the audio clip at time start_t
tw.interpolate_deferred_callback(asp,start_t,'play',0) 
tw.start()
func _on_tween_all_completed(): 
#could stop the audio player with asp.stop(), but prefer to emit a signal to handle action elsewhere
emit_signal("finished")