Trying to hardcode volume in my audio tag in Phoenix LiveView

Hi all!
I’m trying to do something very simple but I’ve been stuck on it for a while. I have these audio tags and I want to hardcode the volume level to 0.1. The code below is not working:

<div class="flex flex-col gap-2 w-fit ml-5">
        <%= for sound <- @currently_playing do %>
          <audio id={} src={sound.url} autoplay loop volume="0.1"></audio>
        <%= end %>

Am I missing something?

Oddly, there is no volume attribute for <audio> and <video> tags, you can only set it with JS: document.querySelector("audio").volume = 0.1. I have no idea why this is the case but it is what it is ¯\(ツ)

MDN docs

1 Like

Hey, you again! Hello! :slight_smile:
Yeah I discovered that recently… so strange. Here’s where I am now:

def audio_player(%{name: _, url: _} = assigns) do
      <audio id={@name} src={@url} autoplay loop controls/>
            var audio = document.getElementById("<%= @name %>");
            audio.volume = 0.1;

Seems like the script is loading faster than the audio tag, trying to figure out a way to delay the script atm

Hello :slight_smile:

Read up on JS Hooks, you should be using those.

Otherwise, in more vanilla contexts (ie, without LiveView) there are a few ways to ensure the DOM is loaded before JS runs. Phoenix uses the defer attribute for the script tag: <script defer src="..."></script>. You should really be using JS hooks, though! Not only are they reusable, they play nicely with LV.

1 Like

I’ll look into this, thanks so much!

1 Like

I do it now for the audio with phoenix live view and for work the buttons(Play, Pause, Vol +, Vol -) and the Presence of the Phoenix hide the built-in browser UI (by removing the controls attribute from audio) and instead build your own interface and control the playback using Javascript.
You get the element by the ID in this case is #player.

          <button onclick="document.getElementById('player').play()">Play</button>
          <button onclick="document.getElementById('player').pause()">Pause</button>
          class="bg-orange-400 rounded-full"
          onclick="document.getElementById('player').volume += 0.1"
          Vol +
          class="rounded-full bg-lime-200"
          onclick="document.getElementById('player').volume -= 0.1"
          Vol -

        <%= if @is_playing do %>
          <button onclick="document.getElementById('player').pause()">
            <.icon name="hero-pause-circle-solid" />
        <% else %>
          <button onclick="document.getElementById('player').play()">
            <.icon name="hero-play-circle-solid" />
        <% end %>

Like document.addEventListener("DOMContentLoaded", function () {...});