2

I want to play sound (.wav, as byte[]) in one of my apps I develop using Vaadin 14. Unfortunately I did not find a component for this use case.

Vaadin 8 offered Audio (https://vaadin.com/api/framework/8.5.2/com/vaadin/ui/Audio.html) but it is not available in Vaadin 14.

I think there is a solution by simply using HTML <audio> and import this.

<body>
  <audio src="test.wav" controls autoplay loop>
    </audio>
</body>

Is there also a "Vaadin 14"-solution for this?

Michael Kemmerzell
  • 4,802
  • 4
  • 27
  • 43
  • 1
    As noticed in migration guide here : https://vaadin.com/docs/v14/flow/migration/5-components.html, it's exactly the solution- using a ` – anasmi Sep 30 '19 at 12:19
  • 1
    You could create your own `Audio` component using the ` – kscherrer Sep 30 '19 at 12:21
  • I stand corrected - anasmis approach (see his answer) is much better and easier for this "simple" html element. Do not follow my suggestion of creating a polymer template. You would need to do this only for more complex things. – kscherrer Sep 30 '19 at 12:37

3 Answers3

11

As we mentioned in comments, there is no out-of-the-box component in V14, but it's quite easy to make an own one as described here : Creating a Simple Component Using the Element API :)

So I've checked it briefly and this seems to work:

AudioPlayer.java

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Tag;

@Tag("audio")
public class AudioPlayer  extends Component {

    public AudioPlayer(){
        getElement().setAttribute("controls",true);

    }

    public  void setSource(String path){
        getElement().setProperty("src",path);
    }
}

Using:

AudioPlayer player=new AudioPlayer();
player.setSource("https://file-examples.com/wp-content/uploads/2017/11/file_example_WAV_1MG.wav");
add(player);

I don't have any music file locally, so taken some random one from internet and passed as a source. That's, of course, not a bulletproof solution, just a proof of concept : )

anasmi
  • 2,562
  • 1
  • 13
  • 25
  • Thank you so much for this great answer! It works like a charm. I am still pretty new to Vaadin and your example did so much more than simply solving my issue. Now that I see your example the @Tag makes so much sense... – Michael Kemmerzell Sep 30 '19 at 12:45
  • Your solution works perfectly on desktop browser but does not work on mobile - any idea why? – Michael Kemmerzell Oct 01 '19 at 06:33
  • Not sure yet. What phone have you tested? This might be related ? https://stackoverflow.com/questions/34837930/audio-tag-autoplay-not-working-in-mobile Or how exactly it doesn't work? Doesn't play an audio? – anasmi Oct 01 '19 at 06:35
  • I tested it on iOS (Firefox, Safari and Chrome). Instead of the play button there is shown 'error'. I tried to disable the 'autoplay' but it does not fix the issue. – Michael Kemmerzell Oct 01 '19 at 06:37
  • Let me try on my phone also – anasmi Oct 01 '19 at 06:38
  • I have quite an old version 10.3.1 of ios, but it works here on my phone(Chrome and Safari). What are you using a as source? – anasmi Oct 01 '19 at 06:43
  • I am streaming my audio file (see the comment down below). – Michael Kemmerzell Oct 01 '19 at 06:45
  • 1
    Could you try to replace with an url from my example in test purposes. Does it work in this case? – anasmi Oct 01 '19 at 06:47
  • The audio works if I use your audio file from the comment so the issue seems to be with the StreamResource. – Michael Kemmerzell Oct 01 '19 at 06:47
  • 1
    Alright :/ Similar issues seem to be reported through years. Could you try , first, setting `MIME` type as discussed here https://stackoverflow.com/questions/26406923/vaadin-audio-element-doesnt-work-when-i-use-it-to-play-m4a-sound-files-vaadin/26408896? – anasmi Oct 01 '19 at 06:53
  • 1
    Hehe I found a fix! You have to set the ContentType for the stream to make it work. I will add it to my comment below. Thank you so much for your help again! – Michael Kemmerzell Oct 01 '19 at 07:01
  • Cool!:) No problem, great you've found a proper fix! – anasmi Oct 01 '19 at 07:02
5

I want to add a short addition to anasmi's great answer for those who may use streams.

Anasmi's AudioPlayer.java:

public void setSource(final AbstractStreamResource resource) {
    getElement().setAttribute("src", resource);
}

To make it work you have to set the content type for the stream:

var stream = new StreamResource("foo", () -> {
                        byte[] data = getBytesFromFileMP3(soundfile);
                        return new ByteArrayInputStream(data); })
                        .setContentType("audio/mpeg"); // For MP3
Michael Kemmerzell
  • 4,802
  • 4
  • 27
  • 43
3

I would make a little addition to Anasmi's answer too - if you want to play the sound on purpose (like when clicked on a button or something like that), you can add method play in this way:

public void play() {
    getElement().callJsFunction("play");
}

Hope it helps someone.

Lohi
  • 547
  • 4
  • 15