Problem/Motivation
After #1174892: File field formatters for rich media display with <video> and <audio> HTML5 elements. Drupal core can display HTML5 audio and video players for uploaded files. On the top of that, in 8.5.0 we had Media source plugins ( #2924631: Media sources for local video and audio support )and Media types ( #2934962: Ship local audio and video media types in Standard ) for audio and video local (uploaded) files.
A very common requirement, however, is to avoid serving big files from the webserver, and deliver directly remotely hosted audio/video files (for example served from S3 or similar) or even streams of audio/video (such as a radio audio stream, etc).
It would be great if Drupal could extend the support for audio and video HTML5 tags to remote URLs as well.
Proposed resolution
- Create new HTML5 formatters for link fields: audio_stream and video_stream (naming could be improved)
- Create new media source plugins for remote audio/video that should be rendered in audio / video tags
How is this different than oEmbed included in #2831944: Implement media source plugin for remote video via oEmbed that also allows remote content embedding?
oEmbed is a format that allows arbitrary remote content being embedded on a host page. Each oEmbed provider (e.g. Youtube, etc.) is responsible for providing the full content to be rendered, and because of that this is usually rendered inside an iframe tag.
This issue, on the other hand, aims at providing the ability to use native HTML5 players for audio and video files that are hosted in a remote location.
Remaining tasks / to be discussed further
1) Figure out naming / UX so that this doesn't create excessive confusion with oEmbed.
Unfortunately the oEmbed source label committed in #2831944: Implement media source plugin for remote video via oEmbed is "Remote video", which, although user-friendly, is somehow innacurate. It will probablycreate some confusion having another "Remote video, but now for files" option there. The proposed patch labels the new sources "Audio stream" and "Video stream", which may sound too technical, and strictly speaking are also a bit innacurate, once they can also be used for remote files that are not streams...

2) Figure out where to expose the new formatters. An initial proposal is to enable it only on Link fields that are attached to Media entities.
An argument could be made that one could want to legitimately render an audio player for a link attached to a Node. Enabling the formatter to all link fields, however, would expose the option to the (presumably) way more common links that are not audio/video files.
This is the way formatter config options are shown when the formatter is available for the field:

So if we expose it to all "Link" fields, they will all get these two additional formatters that will obviously not produce any useful markup if the URL the editor enters to the field is not an audio/video file (or stream).
User interface changes
- Some additional options will be present in the formatter selector, when managing the field display settings
- Some additional options will be present in the Media source plugin selector, when creating a new Media type.
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #48 | interdiff_46-48.txt | 1.68 KB | nikitagupta |
| #48 | 2927166-48.patch | 27.02 KB | nikitagupta |
| #46 | interdiff_43-46.txt | 2.12 KB | nikitagupta |
| #46 | 2927166-46.patch | 27.33 KB | nikitagupta |
| #43 | 2927166-43.patch | 27.18 KB | jibran |
Comments
Comment #2
slashrsm commentedThis would be indeed great to support. It won't be possible to simply extend the existing formatters as they assume files and an instance of entity reference field (getEntitiesToView() and such). My suggestion would be to move common code into a trait and create another set of formatters for links.
Attached patch is far from complete but shows what the idea is. Thoughts?
Comment #4
berdiryes, I don't think that is going to work, especially streams often/usually don't have an extension at all and then we can't guess anything.
Comment #5
mayurjadhav commentedComment #7
krlucas commentedRe-rolled against 8.6.x.
Comment #8
krlucas commentedThis patch leaves FileMediaFormatterBase but has it use the new trait.
Comment #9
krlucas commentedFor link fields I don't see how we could know whether the Video/Audio formatter is applicable or not.
As @Berdir points out streams don't have file extensions but the MimeTypeGuesser was able to guess the mime type for an extension-less stream URL (http://audio.wgbh.org:8000). That said...
When testing with an audio stream URL the mime type guesser guessed "application/octet-stream" but when used as the "type" attribute on the element the audio wouldn't play. Removing the type attribute allowed the stream to play. I'm thinking, for link fields at least, we omit the type attribute. (In my testing the type attribute is not even reliable when you do have a file extension: see #2940065: File field formatter for video doesn't work for .mov files)
Are there fields other than links and files which could use an audio or video formatter? I'm thinking the MediaFormatterBase, VideoFormatterBase and AudioFormatterBase added in the patch should be renamed LinkMediaFormatterBase, LinkVideoFormatterBase and LinkVideoFormatterBase.
Comment #10
marcoscanoTrying to move this forward.
Sorry for the big interdiff, but in this version, I have:
- Renamed and moved the audio/video formatters to the media module namespace. Also, renamed some ids to clearly indicate that these formatters apply to
streams.- Made them applicable only to links inside Media entities. This is probably a debatable decision, and the reasoning behind it is that these formatters are not likely to be used a lot, and would pollute all link formatter settings in the system otherwise.
- Added the missing schemas
- Fixed some minor CS violations and TODOs
- Created 2 new media source plugins, which would use link fields (with the appropriate formatters by default) as source (instead of file fields)
- Started some test coverage
Still to discuss:
- There was a TODO left in the code about what to do when the MIME guesser couldn't reliably identify the MIME type of the stream. But once noted in #9, maybe it is not necessary at all if the type is not included as an attribute? Why is it necessary in the first place?
Comment #12
marcoscanoComment #14
marcoscanoSorry for polluting the issue, I was temporarily unable to run tests locally.. but all set now.
Comment #15
marcoscano(sorry, uploaded the wrong file)
Comment #17
marcoscanoComment #19
berdirNot sure about this, but as a formatter in the media module, I guess that's fine for now, we can always expand it.
The name of this method is rather confusing, but I guess it makes sense in the context of file_video/file_audio which are talking about source files?
The file_url_transform_relative() here is also quite interesting, I've only seen that used in combination with file_create_url() so far.
What it does is convert urls that are absolute but point to the current domain to relative, to avoid ssl errors and so on. I suppose it doesn't hurt, but we should have a comment and test coverage for it?
more on that file/stream things, does it actually work to extract a mime type from a URL like that? Could it be a problem that it could be slow in case it needs to download the file for it (e.g. a 1GB high quality video?)
should we also assert some of the formatter settings like size/muted ?
Comment #20
marcoscano@Berdir thanks for reviewing!
1- Yep, I see both points of this too. I feel though that exposing this formatter (which is kind of very specific) to all link fields would be too much... Maybe we could think of adding a setting to the field config, so the user can allow the formatter on a per-field instance? Or some sort of global setting, disabled by default, that would also extend this to all link fields...
2- Yeah the naming is kind of weird for streams, but we are reusing a lot of the
file_*core formatters, so in that context it kind of makes sense, especially for remote files.I've added a comment and a test for the file_url_transform_relative() stuff.
3- it turns out that
\Drupal::service('file.mime_type.guesser')->guess('https://archive.org/download/testmp3testfile/mpthreetest.mp3')returns
audio/mpegand
\Drupal::service('file.mime_type.guesser')->guess('http://bbcmedia.ic.llnwd.net/stream/bbcmedia_radio2_mf_p')returns
application/octet-stream(which I believe is the fallback for a non-guessed type).That said, in this version of the patch I dropped the
typeattribute that was present in an earlier version of the patch, once as mentioned above, when it is present but doesn't match the real file type, the audio player doesn't work. Was the type attribute necessary for some reason?In case that was necessary, I have no idea though if the guesser needs to download the entire file to guess the mime type...
4- Thanks for pointing that out, there was actually a bug in the
mutedhandling... Should be all covered now.Thanks!
Comment #22
marcoscanoComment #24
marcoscanoComment #26
marcoscanoComment #27
phenaproxima"media formatters" is a vague term. Can we expand on what that means? Specifically, this trait is for formatters which deal with media *files* that are viewable/listenable with the <audio> and <video> tags. Therefore, I'd also suggest renaming the trait to MediaFileFormatterTrait.
Should this be an abstract method in the trait?
The comment needs rephrasing -- these are boolean attributes that are only applied if getSetting() has that attribute name set to a truthy value.
Does this not apply to the audio formatter too?
Nit: The parentheses are superfluous.
I wish that this could be a constant, but the fact that we're using a trait makes that impossible (I believe).
#min should probably be greater than 0. A 0x0 video isn't much good to anyone :)
I think "Size:" is superfluous here.
Can/should we also support string and string_long fields? If so, I'm OK deferring that to a follow-up if you want. The problem is that, if the Link module is not enabled, the source field will not be create-able (or even work correctly). It might be preferable for us to alter the audio_stream and video_stream plugin definitions and make them use link fields if and only if the Link module is enabled.
I think we should probably do something like "$label URL", since we are in fact expecting a URL here.
Comment #28
marcoscano@phenaproxima thanks for reviewing!
1- OK
2- Sorry, not sure I get you... could you please elaborate a bit on that?
3- OK
4- The tag allows it, but for some reason, core's audio formatter for local files doesn't include it either: http://cgit.drupalcode.org/drupal/tree/core/modules/file/config/schema/f... . Maybe in the name of consistency we should do the same here, and decide later if both need to be changed to include the "muted" setting for audios too?
5- OK
6- I guess so too. We could possibly make this constant live elsewhere, but I guess it's not worth the confusion...
7- Changed them to 1. While a video of 1x1 still doesn't make much sense, I think it's not worth starting a discussion about "what the minimum reasonable size for a video should be" in this case... :)
8- OK
9- I'd rather postpone supporting these other fields to a follow-up. In this case, I believe this is a rather specific functionality and I'm not sure exposing the formatter to all those other fields as well adds much value. I guess nowadays most sites will have the Link module enabled (once it comes enabled by default on standard, and also other modules depend on it, such as "Custom Menu Links", "Menu UI", "Shortcut", etc). If a site didn't have it enabled and creates a Media type using this source, we can maybe just enable it before creating the source field? Maybe something like this (untested):
10- OK
Comment #29
marcoscanoRe-rolled the patch against HEAD and updated the IS with some more detailed explanation and screenshots.
Also, tagging for usability review.
Comment #30
marcoscanoComment #32
marcoscanoTurns out the failure in #29 was due to the oembed formatter bug after all. Re-rerolled now that it was reverted.
Comment #33
seanbTo be honest I feel this is probably something for a contrib module. I think most sites will not use this, personally I have only had to make something similar once or twice. Not sure how we can properly check this? Maybe if the contrib get's a huge number of installs we could evaluate it again?
I also think having more audio/video options (next to local files and oEmbed) by default could be confusing. This also makes me doubt whether we should add this in core at the moment.
Comment #34
berdirFair enough. That said, pushing the UX problem to contrib isn't going to solve it for those sites that do want to use it, and it's core that seems to be adding OEmbed as "Remote video", which I find *highly* confusing as it can be used many different kinds of embeds?
We are currently relying on a patch in the media_entity_audio project for this. It's a bit weird right now because that is kind of deprecated now with audio/video now also existing in core. If we'd add just that feature there then it would kind of require a 8.x-3.x branch?
The thing is that the contrib patch (#2927099: Support audio streams) did it with a single source that supports both file and link fields. Makes me wonder if we could handle it in the same way. It would be fairly well hidden then, as the source would default to a local field and you'd need to manually create a link field instead if you want to use that.
But I guess there's quite a bit of local file specific logic now in the audio_*file* source.
Comment #35
marcoscanoI agree to some extent :). But an argument could also be made that it is equally "uncommon" to need to upload an audio file to the server, and core currently supports that out-of-the-box, even with a pre-baked media type. I personally would even go a little bit further and adventure to guess that it is likely more probable that you need to render a
videotag from a remote video URL rather than upload mp3 files to your server...That said, I agree with #34 in that, regardless if in core or contrib, the UX confusion will happen with the current naming...
Comment #36
seanb#34
The choice was made to handle remote video's through oEmbed. Since oEmbed would probably not mean anything to most users naming the youtube/vimeo derivative 'Remote video' was a logical choice. At least core should be easy to understand and use by default. I can see that could be confusing when adding non-oEmbed types of remote video. Since naming things is not my speciality I'm not really sure what would be the best way to fix this. Maybe the new module could also rename the core source when adding a new one to make the difference more clear?
The local video/audio fields are relying on local file pretty heavily, so I guess a new source would be the way to go. The main reason we are not using link fields in core media at the moment is because we didn't want the link module to be a dependency. We would not be using most of the functionality for link fields anyways. Contrib modules would be free to choose link/file fields and support them, but I don't think we should make the core audio/video source do that.
#35
I agree uploading local files/videos would not be a very common thing, but since we were trying to create parity with core file fields that seems to make a lot more sense out-of-the-box. Not sure about the remote video URL vs local mp3, but I see your point :)
About the UX confusion, when adding another remote video source I can see there is an issue. See my reply to #34 for a possible solution. Hopefully we don't have to make it more complicated for the 80/90% use case that would never have this problem in the first place.
Comment #42
id.conky commentedRe-rolled #32, and looks like it working fine on 8.9.13
Comment #43
jibranRerolled #32 for 9.2.x.
Comment #45
jibranI think we can use UriItem (uri) here instead of LinkItem (link).
Comment #46
nikitagupta commentedComment #47
jibran1.
we are not dependent on link module. UriItem is in core.
2.
3. This should be uri now.
+ type: file.formatter.mediaThis can just be mapping now.Comment #48
nikitagupta commentedComment #54
chi commentedSeems it is not gonna make its way into Drupal core. I've just published a little module based on the patch from this issue.
It also supports uploading local images for video posters.
https://www.drupal.org/project/media_stream