Supports URL WmfMedia

Hello,

Could you please modify this code from WmfMediaModule.cpp so that it either doesn’t check file extensions (it isn’t necessary on windows since the source resolver will succeed or fail regardless) - or at least only checks file extensions for file:// urls. FPaths::GetExtension cannot be relied upon for http urls.

Thanks.

virtual bool SupportsUrl(const FString& Url) const override
{
const FString Extension = FPaths::GetExtension(Url);

	if (!Extension.IsEmpty())
	{
		return SupportedFileTypes.Contains(Extension);
	}

	for (const FString& Scheme : SupportedUriSchemes)
	{
		if (Url.StartsWith(Scheme))
		{
			return true;
		}
	}

	return false;
}

Here’s an example URL: http://a77.phobos.apple.com/us/r1000/088/Music/v4/ef/cc/3b/efcc3bc5-2c44-297c-f4b4-58f0fbfe55ec/mzaf_1651143538966159731.m4a?q=.mp4

I added the extra dummy request parameter “?q=.mp4” to circumvent the bug. Without it, the mediaplayer fails to open.

I think the function is fine the way it is. If a file extension is present, it will check if it’s supported, and otherwise it will try to find a matching URL scheme. I gave priority to checking the file extension rather than URL schemes, because if the file extension is not supported, then we know that the URL scheme won’t support the source either. For URLs that do not have an extension, it’s a blind shot. It may or may not work, and there’s no way to know in advance.

Now, in your particular case the problem is the .m4a extension, which is an audio stream. This extension is currently not in the list of supported WMF file extensions - an oversight on my part, which I have corrected for 4.11 by adding:

SupportedFileTypes.Add(TEXT("m4a"), LOCTEXT("FormatM4a", "Apple MPEG-4 Audio"));

For future reference, the list of file extensions supported by WMF can be found here: Supported Media Formats in Media Foundation - Win32 apps | Microsoft Learn

File extensions are not meaningful in HTTP URLs. File types are given by the Content-Type header in the http response. The url can have “.foo” as its extension and still be a valid media source if say its ContentType was audio/aac.

In one of our use-cases the “file” is actually dynamically generated text-to-voice and the url looks something like http://…/text-to-voice?voice=brian&text=hello+world

No file extension can be expected in such cases. If FPaths::GetExtension found one it would be completely accidental and incorrrect

We could change…

if (!Extension.IsEmpty())
{
    return SupportedFileTypes.Contains(Extension);
}

… to:

if (SupportedFileTypes.Contains(Extension))
{
    return true;
}

… but I’m not sure if that’s desirable, because it will now fail to filter a vast number of URLs that are definitely not supported by the player. My gut feeling is that I would rather err on the false negative side than the false positive, but I’m happy to discuss further and be convinced otherwise :slight_smile:

That still wouldn’t be right for http urls. The correct way to check for a supported file type is to issue an http head/get and validate the mime type returned in the content-type header. File extensions are meaningless on the web. However, as mentioned the source resolver will already do that.

The source resolver cannot be used for that right now, because that would require a player instance to be created in the first place. The idea is to provide some heuristic to pick one of the (possibly many) player plug-ins for a given URL. It’s a catch 22: we want to only create a player if it really supports the URL, but in order to accurately determine support, we need to create a player.

I think that I may redesign this in the near future as part of introducing media sources, so that the user will be responsible for picking and configuring an appropriate player.

You could issue the HTTP head/get yourself prior to creating the player - ofc then that part would have to be refactored to be async as well.

I’ll think about it. Seems like overkill to me though. The heuristic doesn’t need to be perfect; we just want to give the user some assistance. Also, this is not going to work when working offline. I think for the next upgrade I will give the user more choices to manually override the settings on a per-platform basis.

Or could you at least allow a fallback if your heuristic doesn’t match - in case there is only one player - just try to use that.

Hi iktomi,

I got in touch with Max, and he is continuing to look into ways to improve this. Since this conversation seems to have run its course, I will be marking this post as resolved for internal tracking purposes. If you have anything additional to add, please feel free to post another comment.