How to call javascript functions from other functions (multiple times in a row)?

I see, well what ever works to get the job done. :slight_smile: I just didn’t understand the complexities involved with your project seeing as though this could be a native thing boy was I wrong :wink:

OK - now I have a better idea of what You are after…

AudioSceneTrigger_JHSv1.hype.zip (262.3 KB)

Overview
Scene Loads > Song plays > Song ends > Transition to the next Scene…

Note: No need for “howler.js” for this particular situation.


Once again we are going for simplicity & compactness - only one function is needed (“sceneAudio” - please see bottom of this post). I am not trying to provide a complete solution here - only a concept. In the Demo everything gets rolling immediately with an “On Scene Load” handler but the initial trigger can instead be user initiated (button, etc.) - just haven’t bothered with that here.

You can easily write your own “auto-play” in Hype using a variable… a Scene plays the music but does not advance to the next Scene (e.g. autoplay = false) or runs all the Scenes (autoplay = true). This functionality is not included in the attached Demo.

The General Concept is we match the Scene Name with the Audio tag iD and take it from there.


Audio tags - in the Demo select the rect (Scene01) or ellipse (Scene02) and view the innerHTML:

Scene01

<audio id="audio_01" width="400" preload="auto">
    <source src="${resourcesFolderName}/audio_01.mp3" type="audio/mpeg">
 </audio>

Scene02

<audio id="audio_02" width="400" preload="auto">
     <source src="${resourcesFolderName}/audio_02.mp3" type="audio/mpeg">
</audio>


"sceneAudio" function - called by the “On Scene Load” handler

The “slice” method as used here extracts the last 2 characters of the Scene Name (e.g. "01 or “02”) to match the audio tag IDs (e.g. “audio_01” or “audio_02”).

var whatScene = hypeDocument.currentSceneName();
whatScene = whatScene.slice(-2);
whatScene = "audio_" + whatScene;
	
var myAudio = document.getElementById(whatScene); 
myAudio.play();

myAudio.onended = function() {
   hypeDocument.showNextScene(hypeDocument.kSceneTransitionPushRightToLeft, 1.1)
};
1 Like

Additional Notes:
An example of simplifying things more > put all your audio tags in a Persistent Symbol (“Add to All Scenes” option); that way You have just one location to edit and do not need to create an element for every Scene just to hold an Audio tag. This is a real time saver if You have many Scenes.

Note: In the attached Demo below this Persistent Symbol (rectangle) is placed just outside the Scenes’ boundary on the right hand side, vertically centered.

Now the only thing You need to do to create this sequence of Scenes & music is select the “On Scene Load” handler for each Scene and choose: Run JavaScript > sceneAudio().

AudioSceneTrigger_JHSv2.hype.zip (263.0 KB)

1 Like

Hi Jim,

Thanks so very much for your input here!

So, now I’m faced with a quandary:

I love how dry your code solution is.
But (unfortunately, or fortunately, can’t decide which, lol) I now have it working perfectly with my initial setup. So, I’m really happy that it’s working, but I’m quite certain that my solution is not nearly as elegant as yours. So, now I’ve got to think - do I want to keep my working code as-is and move on to building in my next functionality (ie displaying audio track time, displaying audio track length, and possibly audio scrubbing with a dragbar). Or, do I want to redo my mockup with your code in order to sleep soundly knowing that a nice dry solution is under the hood?

I’ve included my finished mockup so you can see exactly how all of this is supposed to work along with navigation and regular audio controls (play, pause, stop).

In general, I would have loved to have been able to just use Hype’s native audio controls (and thereby avoided howler.js), but I know at the very least I would need to be able to pause. And since Hype can’t do that (yet! I hope future Hype versions will have more robust audio control, :slight_smile: ), seemed like an audio library like howler.js was the only way to go.

Here is the working mockup with full functionality:

autoPlayTest6.zip (237.5 KB)

In your opinion, is the example above working well enough to keep my code as-is? Or if this was you, do you think there is enough benefit (with your cleaner code) to refactor mine with your solution?

Again, thanks so much for your time and input with this. Super helpful and learning a ton!

Hi Raleigh!

I won’t be able to respond tonight to your last post - but…

Here is a file for you inspection that has many of the basic features you have previously described and are in your example Hype project (in terms of operational function):

AudioSceneTrigger_JHSv4.hype.zip (274.5 KB)

“Auto Play” option, “Play~Pause” button, “Auto Scene” advance, “Manual Scene” change.

Have a go with it and see what You think. I will be in touch, here, tomorrow to go over this project file and your other questions

Hi Jim,

I can’t thank you enough for you help with all of this!
The way you used persistent symbols in your example is awesome.

The blessing and the curse for me at this point is that the code I was working on originally is now working absolutely perfectly (albeit less elegantly than I’d probably like).

Here is my most recent version :).

I now have all of the various audio and nav buttons working exactly the way they should. Tricky thing is, it took a sizable amount of tweaking to get the exact behavior I needed from all of the various controls, and I find myself taking a big gulp at the notion of getting a totally new setup up and running (despite how awesome of a setup it is).

The other huge factor is that I’m on a relatively tight time frame with this project and I’m afraid incorporating restructured code from the ground up is going to set me back time-wise farther than I can afford.
As a result, I’m inclined to keep my current code as-is and finish it off with the last functionality I need for the client. So, now I’m faced with the task of pressing on and building out the code in its current working state (for better or worse).

I hope you don’t feel like any time has been wasted with the code examples you helped me out with. Looking at your examples was hugely instructional and I had a number of important lightbulbs go off (so thank you again for that. I appreciate the help, and none is taken for granted).

All of that having been said, here is where I’m currently at:

Tonight I figured out how to display the duration of the currentSong in the innerHTML of an invisible box on each scene. I’m hoping I can use this knowledge to figure out how to display the currentTime (in another box) as the song plays using the howler.js’s seek() method, as well as how to add 2 buttons to skip the audio ahead or behind by 10 or 15 seconds.

Honestly, what I feel I am going to have a sizable challenge with is how to add an audio scrubber slider (and possibly a volume slider). In that regard, if you have the time and inclination, would you have any input on how I could construct an audio scrubber and incorporate it into my current working code?

In my research I came across your excellent post on building a volume slider. Could your volume slider setup be used to control the audio position like a scrubber?

Would so appreciate any input you might have.
It’s a huge help, thx again!

Hi Raleigh!

Well, You have anticipated my response. You have everything working so I would stick with it.

However, there was not anything in the howler.js code (as You have implemented its feature set) that could not be done with standard HTML & JavaScript - and You have my example project for future reference.


As regards the audio scrubber there are two (possibly three) approaches:

First approach: use the browser's "default" audio player - which You can control the functionality of (play, pause, etc.) with JavaScript using an audio tag as demo'd in the project below:

AudioSceneTrigger_JHSv5.hype.zip (119.7 KB)

However, each browser presents a different default look, size and positioning relative to the containing element (try the attached demo with different browsers to see what I mean). The height is fixed for a given browser's "default" browser audio player but You can control the width in the audio tag - example: style="width:500px;"; though when You shorten the "default" player too much it will lose functionality (e.g. volume control) due to the reduced real estate for the controls.

So You have limitations in how You present your page. If You go the browser "default" player route I would recommend placing it at the bottom of the page where the variation of different browser presentations is less noticeable. (As per my attached demo.)

Safari & Firefox have the most discrete default appearance. Chrome & Opera are way too much in-your-face.


Second approach: If You want a high level of control of your player's appearance, I'd say You are better off rolling your own, but of course have to write the functionality. The "volume slider" thread you sited in your last post would definitely be a good place to start for the concept of creating an audio scrubber~playhead. Try searching this forum for other player interfaces. (In this instance searching for "video" instead of "audio" player might yield better results... same concepts.)


A third approach... the Shadow DOM... to help You wrangle the default look of the "native" browser interface. Never have delved into this environment, but it looks interesting - one site discussing it is here. Google "Shadow DOM" to explore further. I have no experience to offer an informed opinion or give advice.


And now I will leave this discussion - with Best Wishes in your endeavor. :pray:

1 Like

Great, thanks again for your very helpful input Jim!

I think I will need to take the second approach you mentioned as I will need more control over the look and feel of the controls (and browser consistency). Looks like I will need to build it from scratch. I will indeed search for ‘video’ instead of ‘audio’ - I think I’ve scoured just about every one of the ‘audio’ ones already, lol.

Great to know what my options are though - have never heard of the Shadow DOM approach. Looks interesting - I will take a look when I have a moment.

Thanks again for sharing your expertise, all the best!

1 Like

Hi Raleigh!

I noticed an error in the “Volume Slider” example Hype project. Please use this one instead:
VolumeControlTimeline_JHSv2.hype.zip (274.6 KB)

Also - as long as I’m here - please see this link regarding getting & setting of audio time (HTML DOM).

You will want your audio scrubber to be set up as a percentage (as is the Volume slider), so the scrubber will self-adjust to the length of whatever audio track You are working with; which means of course You will need to know the duration of the audio track… (HTML DOM).

Thanks very much!
I will used the updated ‘Volume Slider’ for reference instead.

I think I’ve found a great tutorial to reference as well.
Going to try and implement it tomorrow.
It’s a really paired down example with only a play/pause button and progress bar slider.
Crossing my fingers!

1 Like

JimScott,

Thanks again for your great input a while back!
I had to switch gears to another feature and now I’m circling back around to this audio player/scrubber. The good news is, I was able to reverse engineer a video scrubber Hype example that works great!

Tricky thing is, it’s done with the standard web audio API and not howler.js. I tried to incorporate this audio player/scrubber into the main website and not surprisingly, it worked in an isolated way, but not in an integrated way with what I have already built. Unfortunately I am needing to stick with howler.js for the main website since I am using it for some other features and it’s pretty well intrenched now, otherwise, I’d consider retooling the site to work with standard HTML and JavaScript.

So, I’m now attempting to get the audio player/scrubber I built to get with howler.js.

Frustratingly, once I attempted to replace the web audio stuff with howler.js, some aspects work and some don’t. In particular, regular play() and pause() work great, but for the life of me I can’t get howler.js’s seek() method to work! Don’t know why. The seek() method (with no arguments) is, from what I understand, supposed to return the current time of the audio. Do you (or anyone else!) know what I can do to get this simple example to work with howler.js?

Here:
Audio Scrubber W Web Audio API.zip (1.8 MB)

is my working example that incorporates the web audio API, and

Here:
Audio Scrubber w Howler js.zip (2.2 MB)

is my (only partially working) example with howler.js. They are almost identical, but one difference worth mentioning is that the web audio example loads the audio with a rectangle shape’s innerHTML placed in the scene, whereas the howler.js example loads the audio from a function that creates a new Howl audio object (like it does in the main website).

Do you (or anyone) have any ideas at all with what I’m missing?
I feel like if I could figure out how to get that howler seek() function to work, than I’d be good to go! I’d so appreciate any help or input on how to get my audio/scrubber working with howler.js.

All the best and many thanks!!

Regarding the “Web Audio” & Howler" ZIP files: The downloads only contained PNG files.

Ah, many apologies!!
Here are the correct files that I intended to attach:

Update:

I have a friend across town that is great with code - although he is not a Hype user, I emailed him outlining the problem and he made a suggestion of how to configure things to get seek() to work (that was who the screen shots were for when I mistakenly attached the png’s - again, so sorry about accidentally uploading those instead of the intended Hype files).

Great news is, with his changes, I now have the timeDisplay working!
So, seek() is now working to an extent.

Unfortunately, the Scrubber is not only not moving when the audio is plays, but when the Scrubber button is moved, a console error is displayed that says:
Error in undefined: ReferenceError: Invalid left-hand side in assignment

Any thoughts at all what this might mean or how to get the Scrubber working?
It’s so puzzling considering the web audio API version and this howler.js version are basically identical. Seems the problem has to be in the changeAudioTimeBasedOnScrubber or the setupAudioToScrubberSync functions, but they are so alike. Seems like they should work the same way.

Here is the updated Hype file - do you have any thoughts at all? Thank you so much for any input you might have.

https://www.dropbox.com/s/kpvnu6vhan2w5vt/AudioScrubberHowler.hype.zip?dl=0

sunny day :slight_smile:

2 Likes

Hi Hans-Gerd,

Thanks so much for taking a look at this!
I downloaded and tried to open your example, but it wouldn’t open. Instead got this message: Document Version Incompatibility - The document you are trying to open was created with a newer version of Hype and cannot be displayed.

Are you using Hype 4? :wink:
My current version is 3.6.7.

Would you possibly be able to send me a version that I can open with Hype 3?

Thanks again!

ah … sry

FYI: i removed the audiofile to get it up here …AudioScrubberWHowler3.hype.zip (36.8 KB)

4 Likes

And…it works!!!

Wow, thank you so much for your help with this HansGerd!
Can’t tell you how grateful I am for your assistance.
And also thanks so much for hooking up the duration as well.
Just fantastic.

Sunny day indeed :slight_smile:

Have a wonderful week and all the best to you.

1 Like

Hi h_classen!

I wanted to thank you again for the help with the audio player.
It’s working wonderfully with my project!

However, the last feature I’m needing to add to this audio player is the ability to click on the audio scrubber and jump to that time in the timeline.

I’ve been trying to modify the clickToTime(); function in Mark Hunte’s video-controller example to get this to work in my project. But the setup is different enough that I’m having no luck.

Do you by any chance have any thoughts on what I can do to get a function like clickToTime() working with my audio player?

Here is the example file I’m working with:

AudioPlayer.zip (1.6 MB)

I’d so appreciate any guidance you (or anyone else) might be able to offer.
Thanks so much!

There’s a bit of complexity in getting the events entirely correct because you have the group as your scrubber; you may want to think about changing the knob to have your on drag action for it to work correctly. I got the basics by adding a “hit box” rectangle element with an opacity of 0% above the slider control. This was to get the width and hit target exacting. Then I added an on mouse click action that looks like:

 	var sliderWidth = hypeDocument.getElementProperty(element, 'width');
 	var percentComplete = event.offsetX / sliderWidth;
	song.seek(percentComplete * song.duration());

Here’s the demo file:

AudioPlayer-fixed.hype.zip (1.6 MB)

But like I said, it isn’t perfect due to the drag on top.

2 Likes