TTMSFNCWXAudioPlayer input options ?

The TTMSFNCWXAudioPlayer only has a URL property to set. I have an MP3 file in a TMemoryStream that I got from a site, and the file there disappears fairly shortly. (You make a request and they advise you to DL it within 30 minutes when it gets deleted.) So I can save it to a local file or DB or something. But once it gets deleted from the remote server and I have a local copy (usually in an array of TMemoryStreams) how can I play them?

To speed things up at runtime, I'll be preloading the files into TMemoryStreams. They're mostly quite short, maybe 5-15 seconds each.

Also, if I want to play a series of these short audio files (tracks?) in sequence that I don't want pauses between, what's the best way to do that?

Hi,

The TTMSFNCWXAudioPlayer uses the HTML audio tag to initialize an audio player, so it covers the functionality the tag offers.

The two ways to play an audio is via an online URL that hosts the audio or by a base64 string. If you can convert your TMemoryStream to a base64 encoded string then you should be able to assign that to the URL property without problems. You'll also need to add the prefix for mp3 so it is recognized: data:audio/mp3;base64.

This will depend on the capabilities of the HTML audio player. You could try the OnEnded event which is triggered when an audio track has finished playing. From there assign the new base64 encoded audio file and play it.

Several articles I've found suggest that the audio tag's src element can specify local files. See this article where there are several examples:

But there are also things on StackOverflow suggesting it's problematic:

Another useful post:

Can you explain how to do this in a bit more detail?

If I DL binary files like an MP3 file, do they get sent as base64 encodings? If so, then I can just do the encoding and save them that way because they'll be forwarded on later.

The examples in the MDN docs are actually relative paths to the HTML file, those are still hosted somewhere. If your example HTML is on https://example.com/myplayer and the files are on https://example.com/myplayer/myaudio.mp3 then you can indeed use src="myaudio.mp3".

If you'd be able to access any files by writing file://full_path_to_audio_on_your_local_file_system, that would be quite insecure. So browsers naturally want to prevent that.

These solutions have something in common and that is using an HTML input field as a file picker to prompt the user to open the file they want to give access to. That way it was the users' own decision to provide access to their file. In your use-case this isn't something you want to do.

Normally if you download a binary files then they are stored in a binary format. Base64 is used to represent binary data in string format and you can't really store binary data in a string format after all. So you'll need to convert the binary to base64 when you load it into your application. Depending on which framework you are using, you could do this with TNetEncoding for example. You can do this conversion before assigning the URL to the audio player (or just store them as base64 right away when you load them).

The confusing part here is why the prefix/header is needed. When you convert a binary file to base64 it does not automatically come with a prefix/header. As I mentioned, it's just a string representation of your binary file. As soon as it gets the prefix, it turns into a data URL that is understood by the browser: Data URLs - HTTP | MDN
data:[<mediatype>][;base64],<data>

1 Like

I understand the security issues in general, but this component is kind of weird in that context. I don't know if it's actually running inside of a web browser, or if it's just some magical application of fancy javascript, or what. But it's totally self-contained and is a component that's intended to stand alone on a VCL or FMX form; or on a WebCore form -- in which case, I don't know if it's still an isolated standalone thing or if it transforms into just another HTML tag on the page.

This isn't just an idle curiosity, as it helps to know what browser context applies to this component? It seems the Base64 data: option has different size limits based on the browser -- Opera is up to 65k; FF goes up to 32MB, Chromium goes up to 512MB, and Webkit is 2048MB. Where is this specified for FNC components implemented this way?

For the TMS FNC WX Pack it is an embedded web browser that hosts the components, so underlying it's still HTML and JavaScript. The exception is WEB, where you don't embed a browser inside the browser. For WEB the necessary HTML and JavaScript is added to the page directly.

It uses the browser engine of the platform similarly to TTMSFNCWebBrowser (so for Windows it's Edge Chromium / WebView2, for macOS and iOS it's Safari / WKWebView and for Linux it's WebKitGTK). 5-15 seconds of base64 encoded audio should be doable regardless of the underlying browser unless we are talking about huge file sizes.

1 Like