Audio element gets rendered disabled in Safari/iOS 14

Hi,

I’m implementing a chatbox using Vaadin 14, which is capable of recording and presenting audio messages.

The recording part works fine, but when the recorded audio gets stored in server storage and would be loaded to UI using a custom Audio component, it comes totally disabled in iOS Safari.

I have used StreamResource to set the src attribute of the Audio tag (the URL would be generated dynamically by Vaadin itself) and the code looks like the following.

Let me emphasize that, the feature works properly on all devices and browsers except iOS Safari.

CODE :: Loading the Audio file as StreamResource >>

StreamResource audioResource = new StreamResource("resourceId", () -> {
	try
	{
		return new FileInputStream(new File("path_to_audio_file"));
	}
	catch(final FileNotFoundException e)
	{
		e.printStackTrace();
		return null;
	}
});

AudioPlayer audioPlayer = new AudioPlayer(/*Element ID*/"audioelement", /*src attribute*/audioResource, /*autoplay*/false, /*controls*/true);
add(audioPlayer);

CODE :: AudioPlayer element >>

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

@Tag("audio")
public class AudioPlayer extends Component {
    private StreamResource src;
    private String elementId;
    private boolean autoPlay;
    private boolean controls;

    public AudioPlayer(String elementId, StreamResource src, boolean autoPlay, boolean controls) {
        super();
        setSrc(src);
        setElementId(elementId);
        setAutoPlay(autoPlay);
        setControls(controls);
    }

    public StreamResource getSrc() {
        return src;
    }

    public void setSrc(StreamResource src) {
        this.src = src;
        getElement().setAttribute("src", src);
    }

    public String getElementId() {
        return elementId;
    }

    public void setElementId(String elementId) {
        this.elementId = elementId;
        setId(elementId);
    }

    public boolean isAutoPlay() {
        return autoPlay;
    }

    public void setAutoPlay(boolean autoPlay) {
        this.autoPlay = autoPlay;
        if (autoPlay)
            getElement().setAttribute("autoplay", "");
        else
            getElement().removeAttribute("autoPlay");
    }

    public boolean isControls() {
        return controls;
    }

    public void setControls(boolean controls) {
        this.controls = controls;
        if (controls)
            getElement().setAttribute("controls", "");
        else
            getElement().removeAttribute("controls");
    }
}

Hi…It has a HTML5 component with autoPlay set, which isn’t very playing when the page is stacked, yet is consequently playing when the revival state says the client squeezed play; in that situation the component is delivered in a playing state…

Another issue is that playing is decoupled to some degree from the component - if the iPhone goes to bolt screen, some implicit sound controls are apparent, the application gets no update if the client stops or looks for utilizing the inherent lock screen regulator, thus then its state is not, at this point precise.

[printed circuit boards]
(https://www.7pcb.com/PCB-Fabrication.php)

Hi,

Very strange behavior by iOS/Safari.
When you are building the StreamResource object, you wanna make sure that the file extension has been provided. otherwise, iOS/Safari won’t consider the src attribute of your audio tag valid.
below small change in initiating the StreamResource object fixed the issue.

StreamResource audioResource = new StreamResource(/*Added .mp3*/ "resourceId.mp3", () -> {
	try
	{
		return new FileInputStream(new File("path_to_audio_file"));
	}
	catch(final FileNotFoundException e)
	{
		e.printStackTrace();
		return null;
	}
});

AudioPlayer audioPlayer = new AudioPlayer(/*Element ID*/"audioelement", /*src attribute*/audioResource, /*autoplay*/false, /*controls*/true);
add(audioPlayer);