#Media
1 messages · Page 1 of 1 (latest)
@gilded tangle let's chat !
Here is an interesting media source architecture issue that I am working on https://github.com/home-assistant/architecture/discussions/1201
Media search proposal is already approved https://github.com/home-assistant/architecture/discussions/677
I haven't really touched anything media related in HA yet, but I'm curious now, so I'll definitely have a look at that one
Media search would be awesome! HEOS would be able to implement that!
@ashen birch what would you actually want to search for? A name: str | None and an allowed_content_types: set[MediaClass] as suggested?
Do you remember what Erik meant with searching for asterisks (image/*)? If we only filter down to MediaType that should seems unnecessary?
Let’s follow the search method that music assistant uses
Basically we should allow searching for artist named Beatles
So that would be media classes I think? Not file types
I’d suggest making MediaType optional with the default None to mean all types supported by the platform. That’s how most UI implementations work as well.
(That’s also how music assistant works)
Hm. Not sure we are on the same page yet. I opened a draft PR with some changes so we can get a common understanding of what we should be building https://github.com/home-assistant/core/pull/140294/files
@gilded tangle left a comment
I think the main thing is that we should add this to media players only first
and not media source
I started adding it as media source because when checking browsing a lot of media players rely on media_source.async_browse
That’s why I thought about adding it to source first and player as follow up
But I guess we could do either
I think that we should only initially offer search for media players that have their own backing collection (ie spotify, music assistant, sonos)
let's avoid the whole "how are we going to merge search results from different sources"
That’s something I was already wondering
But also how would we handle a search for albums & artist and a title of „the beatles“
Which would give you both the album as well as the artist
Just throw them in the same result set?
that's up to the integration
I think for now we can just allow a single media type ?
and not multiple
so you either search for albums or artists
not both
Maybe we rather limit that in frontend for now then
Because for service responses it shouldn’t matter as much
But changing it if integrations already implemented it that way is annoying
right
so this should be pretty straightforward, the only thing I can't quite wrap my head around are the function parameters. I think we should have both query and allowed_media_class to allow for server side filtering. But should we also keep media_content_type and media_content_id to ensure we only get content relevant to that integration? New draft PR https://github.com/home-assistant/core/pull/140321/files
Content Id is to search in a specific folder
I wonder if we should add a new Boolean to folders if they are searchable.
And if so, we pass content type and ID of folder, query and type were looking for
So you can go into a playlist folder and search playlists
I think adding "searchable" makes sense. I'd also suggest that Content Id be optional. For example, search in HEOS is global -- not constrained by a specific part of the browsable tree. It can be scoped to a specific music service (or multiple), which could be represented as a top-level folder, which then is "searchable=True". However, I think you'd want the UI to allow search at anytime, regardless of where you've navigated, thus an empty content id.
Instead of “allowed”, I think “target_media_classes” makes more sense.
It already is optional or did you mean something else
In the method parameters what would media_content_type parameter be used for? Here's how I understand them now:
media_content_idcontainer to search (orNonefor a global search). It would be a Media item that was markedsearchablefrom the platform's browse.query: The search string itselftarget_media_classesan optional set of the types of items to return in the results. An empty set means all available items are included.
I'm wondering if we actually want target_media_classes to be target_content_types (with str as a valid option), as the platform may have unique items not currently represented in HA.
To be honest, I'm unclear on why we have both MediaType and MediaClass anyway. 😅
media_content_id is not enough, it always needs to be paired with a media_content_type. That's been a design mistake from Past Paulus
Same with media classes and media types…
I think that we should stick to media types, because if we don't, we cannot make a UI for it
every field in the UI would end up being a text box in the end if we were to do that 🙈
Oh right, I forgot about the pairing of content_id and content_type.
To clarify, stick with "media_classes" (what Josef has in the PR now?)
yes
Seperate question (related to Media), what's the right way to represent paging in browse? I was thinking I could essentially create a virtual folder to represent the "Next Page" as the last item, but that feels clugy, especially if the service action is being used programatically.
we don't currently support pages
so yeah virtual ones is possible, also feels hacky
especially because the folder would be shown at the top I think ?
I'll play around with it and see what happens
Another question related to browse, should I put all of the HEOS-specific sources at the root level alongside the media_source root items? (per screenshot) Or would it be better to put them all in a sub-item (i.e. "HEOS Music")?
(The first 7 items come from HEOS, the others are coming from media_source)
Sorry if this isn't the right place to ask, happy to take it elsewhere too
As a user I'd definitely rather have them in an Integration specific folder
That’s what plex and sonos are doing at least maybe check those
Sounds good and makes sense. Agree with consistency.
I believe we put all individual sources and then media source folders
No specific heos folder
Hm I only have a Sonos to test here
And it’s just one folder for favorites so hard to say which thing they follow
Anyway consistency is important
I did an analysis of all 39 integrations that implement async_browse_media. Of these, only 9 combine media source and integration sources. Paulus was correct that that the standard is to put the individual sources first:
- 7 integrations add local sources before media sources (music_assistant, forked_daapd, kodi, roku, sonos, sqeezebox, and yamaha_musiccast)
- 1 integration adds local sources after media sources (cast)
- 1 integration adds an integration folder before media sources (apple_tv)
Josef, note, Plex does not support media sources, it's only integration sources.
There are other conditional root-level items that can appear alongside Favorites, such as "Music Library".
Would this be valuable for me to submit an architectural item to memorialize the approach?
I would just open a dev docs PR and document it as such
Will do!
The only thing is that now all integrations need to care about overlaps with other integrations sonos/spotify&plex and so on
True, however I don’t know if there are any actual products that support both a local source and the same one through a music source. Do you know of any that concretely do?
Maybe Sonos, but the integration doesn’t expose integration music services (ie Spotify). I don’t know if that’s a limitation of the API, or just not implemented though.
Plex doesn’t appear to expose browsing Tidal (their integrated music service) through their APIs.
sonos does with both plex and spotify
Right, but is there an overlap with sources Sonos provides via the integration itself?
if I understood it correctly there is an overlap, but they just pass those to the integrations
like sonos would have a plex source, but they call plex.browse for those instead
Yeah, it does that in the integration, I’m just not sure the Sonos library or APIs actually can browse directly though, meaning there was a potential overlap.
(And they chose to defer to the built in music source versions)
Seems like it should intuitively though. 🤔 HEOS does. However HEOS doesn’t offer a way to play something from the Sonos integration. At least, I haven’t been able to figure out how to translate that. 😂
their app does yes
Yeah
like you can play something from plex in the sonos app
Oh I know, but do their APIs and the SoCo lib allow that?
Just checked their source code, it does
Looks like it’s a different API with different auth in the cloud than when connecting to the local device. Interesting.
Fun it’s SOAP 😂
Sonos doesn't allow browsing spotify library natively
But Sonos can play Spotify links
so instead we have this cool thing where if you have Spotify integration set up, you can browse Spotify via Sonos media browser
I added pagination parameters. Mind checking if you’re fine with the spec then I'd continue with tests and try to give frontend a shot (although that is still very strange to me)
Got a link again
ATTR_SEARCH_OFFSET_OR_NEXT feels stronge to me. Is that meant to mean page index offset or record offset?
And allow str? What would that be for?
Typically I’ve see record pagination using the combination page size and index or record start and end.
I've seen APIs (in general) that don’t work with offsets, but rather return a next URL you need to query as is to get the next page
That’s true, I’ve seen those too, but how would an integration return a next url that would get passed in here? I wouldn’t think we’d want to expose the underlying API’s next URL. That feels like a leaky abstraction.
Hm probably true
I would just start without pagination for now 🙂
Yeah, I agree. I’d want to solve paging for Browse too. I’ll see if I have time to submit an arch proposal for that this weekend.
this looks great @gilded tangle
@lilac trail just want to keep you in the loop, we're working on media search for HA here
it's following the approved architecture issue
How would we want to handle wildcards in the search query? I’m not sure all platforms will support it, but HEOS can accept “Beatles” to match that exactly in metadata or “Beatles*”. Would we want the implicit behavior to be “Beatles” or exact match? Or leave it up to tie platforms?
lol I can’t figure out how to escape an asterisk when on mobile
leave it up to platforms
I would say
in general, all searches are now considered to have a * I would expect
like, we're not using AND and NOT anymore either
beatles OR rolling stones AND submarine
Note that when we implemented the search for Music Assistant, we really quickly realized you need more context, hence we also have the optional artist and album fields to narrow down the search. This is especially important when the search is being used by an LLM to do automated lookups. Only do name lookups on a title is not enough if you want the results to be accurate.
We could also simplify that by accepting a splitter and let the integration deal with it
So in our current API we have the source where search originated
so if you have browsed to an artist folder, you can search within that
or would you expect to just have like 10 fields
query_artist, query_song etc
because voice can fill in those spots ?
while in the UI we would just do query. ?
and if an integration doesn't implemenet it, it can just concatenate all the fields to make a query
you always search on name/title
so MediaType.ARTIST + name "Queen"
or MediaType.PLAYLIST + name "Top40"
But in case of albums and songs, the chances of duplicates increase because the titles/names are not unique so you need/may provide ADDITIONAL context.
For example MediaType.ALBUM + name "Innuendo" + search_artist "Queen"
Which could also have been just the name field but typed as "Queen - Innuendo"
So, its optional context which also makes it easier to implement, an integration that supports it, listens for it
search on just innuendo gets me multiple results. Now in this case MA is smart enough to give back queen first as that is in the library but this could also have been something you dont listen often and then there is a potential of returning wrong items. Again, with automated searches. If you browse manually yourself you obvisously just pick the correct one by hand
So that is why we ended up with this now in the HA action...
the artist and album fields are optional but really recommended when an LLM is using the search
If we want to keep things simple for now, I'd opt for the seperator in the searchphrase
Probably better, otherwise it quickly becomes too specific to music
Yeah, and then its up to the integration to actually support that
I understand the problem, though I don’t think we want to push logic for splitting the query into each integration. Is there a way we can still have the parameters but abstracted? Like accept a dict[MediaType, str] called “constraints” or “context”?
let's start simple
it's good to think about these constraints, but they can also be added in step 2
problem is changing that always will require integration changes
which we can't easily do from a core perspective
so I'd rather have the interface 95% correct even if we don't utilize certain parameters for now
Well just like having a response class, we could consider a request class
service call -> internal handler puts it in object -> calls the platform service handler
I like that idea
Hey folks on pagination i had this proposal https://github.com/home-assistant/architecture/discussions/1131
Its very simple, essentially "The page token will be an opaque string, and the format is specific to the integration."
Yeah that would cover most use cases I can think off. Essentially the UI would show a “Next page” as long as the token isn’t None and pass that in to the browse function to get next result set.
It could easily support paging in reverse if it became “next_token” and “previous_token”
the browser can also fetch as you scroll down the page in the UI without a need for a button press. (scroll up for reverse)
Got sidetracked with breaking firmware update in one of my integrations will resume once that is solved
@gilded tangle are you still working on this? Would you be open for others to take over if you don't have time ?
We're quite close to the finish line of this landing and it would be awesome 🙂
If you want to have it in .4 by all means go ahead, I don't have much time this week unfortunately
Or rather until next Thurday
nah no need for .4
because it's foundation, and it needs others to build on top
I was just going through my notes, hence the ping
I’ll implement search for HEOS as soon as it’s ready. Also game to help out with the foundation too.
Wanted to have this done for a while… On business trip the next two days, maybe I find some time on the train
We can ask Andy to pick up your PR if you want, it should be close to finish
I've pushed the suggested changes, please have a look
small status update, other tests are fixed, just need my local media_player tests working and I'll add the test
I am using /media to store ebooks for use in an add-on I maintain (https://community.home-assistant.io/t/new-add-on-minimal-calibre-library-ha-cops). This felt like the most appropriate location to put a books folder. I'm not looking for HA interface to be able to provide access to files via this, but would like to check that it isn't a bad idea to use the media folder for this type of media.
yeah that's fine
Nice!
Wohoo! Nice work @gilded tangle! Can’t wait to implement search in HEOS this weekend! 😃
Really exciting to see search and pagination 🙂 I'm just looking at adding it to Squeezebox now. One quick q - when you implement the action, will you consider supporting an optional extras dictionary? There's application specific parameters I'd like to add for Squeezebox when calling the action - e.g. to be able to override defaults tags which define what fields are returned - or perhaps a maximum number of returned items.
So we have music assistant included in home assistant. I have also seen Kodi & Jellyfin Wouldn't it seem to be a way to merge the best parts into one system?
I may be being dumb, but there's no services.yaml, strings.json in the PR. I see the new action, but there's no UI for it currently.
Sorry if I'm missing something dumb
I see that SearchMedia takes list[BrowseMedia]. Is each BrowseMedia element parent with the search results as children to for example let you split a result across multiple media types, or is this just a list of the child elements - i.e. one BrowseMedia item for each search result with no hierarchy.
Sorry - not clear from the doc.
I also just tried implementing for music_assistant and found that nothing seems to change when implementing the SEARCH_MEDIA feature and function.
I also thought I must be missing something obvious.
Now it all makes sense 😄
whoops 😅
Will there be a UI addition similar to the browse_media button in the near future also?
Well, I applied the service definition and strings locally and the service call now works well
it's always a relief when it's not me being dumb - that's been known to happen 😉
Is this supposed to also update the functionality of the media browser. I assume so if we set can_search, but nothing changes, so I guess the front end pr isn't done yet - is that right? Linked to my earlier question on the SearchMedia result - where should we set can_search?
BTW - thanks again - this is a much needed feature (and hence we're all asking loads of questions while you're still spinning the wheels)
no there is no frontend for this yet, can_search does nothing at the moment
future - likely, near - we'll see
someone needs to build it first 😉
Thanks @gilded tangle
I see that currently search_query is required, but media_content_id is optional. If I'm searching by media_content_id, then I likely won't want a search string as well - it's likely one or the other if the media_content_id identifies a specific item. I might want to seach using the content_id to get more details, but I can't do that if the search_query is required. Is there any reason for them to not all be optional and then to let us raise ServiceValidationErrors if the pattern doesn't work for us
Would certainly love a UI for that ☺️😉
Would it be mostly text search? Can it have filters for metadata?
You can filter the query for the action by content_media_type (e.g. albums, artists, playlists etc.) or by content_media_id and you can filter the response by the class of media, which is integration dependent, but might be "track", or for squeezebox, "audio" or "playlist"
Yes but problem is we don’t know supported filters
once we get results we can see what types are in the results
We'll just have to document the supported media_types etc. in the integration docs. I proposed an adr to extend the standard list of media_types (e.g. include albums, artists etc.) but that didn't seem to be supported, so we can just add the allowed entries in the doc and raise errors for unsupported types
Would also like to see radio and audiobook in supported types 😉
But radio can be covered currently simply by the music type, so that isn't such a problem as audiobook
Let’s first get the basics out and usable before we look into expanding it
I completely agree, just little ideas for the future.
I've been working on the squeezebox integration with this and thinking about the return value from SearchMedia(), which currently takes list[BrowseMedia]. For now it doesn't matter, since it's just the response variable, but if we think about how this will integrate into the media browser at some point, I think this should be BrowseMedia, with the response being its children - i.e the same way we build a response for browse_media.
return BrowseMedia(
title=result.get("title"),
media_class=media_class["item"],
children_media_class=media_class["children"],
media_content_id=search_id,
media_content_type=search_type,
can_play=any(child.can_play for child in children),
children=children,
can_expand=True,
)
For the media browser, I imagine a situation where when we set can_search=True, we get the ability to enter a search string. Then the result from that search would be a BrowseMedia item for the media browser to display . If we're going to integrate the response to async_search_media into the media browser at some point, shouldn't the return type be the same as async_browse_media - i.e. BrowseMedia, rather than list[BrowseMedia]?
I think I follow, you're suggesting that a returned BrowseMedia object is in and of itself the more appropriate container of the results as children, rather than a list of BrowseMedia objects?
Yes - exactly that. That's already the mechanism we use to return a response from async_browse_media for the media browser, so if we want to integrate the search capability at some point, doesn't it make sense to use the same object for async_search_media
Sounds like a reasonable suggestion.
Just thinking that if we release this as it is, then integrating it into media browser in the future will be difficult, and perhaps a breaking change for anyone that's already used the action in its current form
it also makes writing the integration update easier as I've just basically just passed a new search string variable to the code I used to build the browse_media response
i.e. just thinking about search as something which produces the same output as browse
and just updating the browse code to take a search param
ok - squeezebox is done. I need to get a library update pushed. Extending the functions I already had for async_browse_media to take a search string and re-using those made it pretty straight forwards to implement.
Do you already have a PR in? I'd be interested in seeing your implementation.
I'll post it later. Just got to fix a type fail
once this is done, i'll be trying to use this to build some basic voice control blueprints for squeezebox. Combining search_media to find the content_id and then play_media to play it should be pretty straight forwards. "Play favorite classic fm in the den".... Tricky bit will be when the search finds more than one result ... hmmm... Full text seaching in the squeezebox api is pretty basic..
We should just make a real voice intent and solve it for all
The intent handler would just search and then play first result
Sentence matching helps to define filters
Play a song by ARTIST
yes, i've lifted the voice blueprints from music assistant and played around with their structure already
a general voice intent would be v. nice
tricky to make it generic though - integrations define their own media_content_types
e..g. i have favorites, which has a mediaclass of favorite
the naming for albums isn't even standardised - i mean everyone will likely call it albums, but it's not defined as a standard
so, a general implementation might say "play ziggy stardust album", which would want to search the "albums" media content type, but that might not exist, or might be called releases for example. Until now, it didn't really matter what we called them internally, but now we're beginning to expose them in browse_media, search_media and play_media the naming matters more.
i proposed an adr recently to extend that list of standard types to try and improve this, but the feedback was that since it could never be an exhaustive list, we shouldn't make it longer, but i think it makes generalising any of these services or intents more unreliable for users.
PR is https://github.com/home-assistant/core/pull/143261. As you'll see, async_search_media is very short because I'm basically just re-using all the functionality already built for async_browse_media. There's more changes relating to tidying up the media_content_types etc., and making sure that if someone entered something different to what's used internally, that the search & browse still respond correctly.
Is this supposed to be in the Media browser if you don't have NC subscription?
It appears to not work, if you try to "Say" I just get a spinning loading wheel forever. 😕
hm it used to not be loaded in the past
I don't know if it's related, but I now have 2 entries for Home Assistant Cloud - one with the NC icon and one without.
Fixed in latest beta
Hey @ashen birch I saw your comment in the LLM project #1346946515511279696 message re: your PR adding a general search and play intent to the media player https://github.com/home-assistant/core/pull/144269. Very exciting and I thought very interesting for this project as well. If I'm reading it right, if we've implemented MediaPlayerEntityFeature.SEARCH_MEDIA this should just work :-). It did re-raise my question on why async_search_media returns an array of BrowseMedia, whereas async_browse_media returns a BrowseMedia object with an array of children. Wouldn't it be easier for the hopeful future integration of search in the media browser UI to have async_search_media return the same as async_browse_media - and would be more consistent for future implementations. I just raise this now since your PR is likely the first thing using async_search_media. I've added it to the Squeezebox integration - just waiting for a library update to be pushed - so looking forward to having this intent available.
So the return value can still be changed. For integrations the format already includes an object.
My thought was more that the return value from async_search_media is an array of BrowseMedia objects - i.e. children with no parent, so you're using result[0] for the first result, whereas async_browse_media returns a single BrowseMedia object with an array of children. So, wouldn't it be more consistent for async_search_media to return the same structure as async_browse_media - e.g. a parent which we could call something like "Search Results" and then the results are in the children, so the result for the intent would be different.
I guess I don't really understand why async_search_media and async_browse_media return different structures.
I’m missing what you’re saying. If I look at the entity method, it’s a SearchMedia object as return value
Right, and SearchMedia is defined as
class SearchMedia:
"""Represent search results."""
version: int = field(default=1)
result: list[BrowseMedia]
So, why
result: list[BrowseMedia]
rather than
result: BrowseMedia
why's it a list of BrowseMedia objects, rather than just a single BrowseMedia object and use the children to contain the search results. I may be missing something obvious (certainly won't be the first or last time), but we're using BrowseMedia here in a different way to the way we use it in async_browse_media, where there's a parent with children. I know it doesn't really matter, but there doesn't seem to be any reason to do it this way, rather than do it the same way as we use BrowseMedia elsewhere and consistency seems to make sense. Also, assuming at some point we want to use the search results as part of a UI for browse media, then we'll need the parent/child structure.
That whole class is the return value
The reason I made it a list is that during browsing you always have a tree with a common root element. A search could return any branch or leaf of that tree. So to not have to include a common root that logically shouldn’t be part of the search result it’s a list
And in the UI you'll always want to see the results not the root, which would be the children list, hence we might already give it the list
Thanks @gilded tangle I get that it doesn't matter when we're just thinking of the results being used in the action as they are currently. But, if you want to be able to use async_search_media to facilitate search UI for media browsing at some point in the future, then don't you need the parent of the children to provide the parental info - title, can_play etc.. I know it doesn't matter atm, but doesn't doing it with the list rather than parent/child store up potential problems for the future?
In the UI you might wanna see a album next to a title in the search results, which doesn’t really make sense in the usual tree structure of BrowseMedia. Each BrowseMedia child would usually set their own properties so I don’t see why we'd need a root object just for the sake of it
I know this isn't currently in scope, but wouldn't integrating search into the media browser need a "normal" browse media tree with the parent info? I completely get that you don't need this for the action, but if we want to use this function to add search UI in the future, won't this cause problems?
Sorry if I'm fixating on this, but just trying to get something clear in my head.
The UI isn't built yet, so it'll take whatever we give it. As I was trying to say earlier: In a search you would want to present a user only with the children of the BrowseMedia (which is a list) anyways (and not first click on the root element returned by the search). So we'll need to build the UI to handle a list[BrowseMedia] in any case, so I don't see a point in returning that first BrowseMedia root
Yes, I understand it's not built yet (and I'll definately put my hand up and admit I know nothing about front end coding), and I concur completely that you would just want the list, rather than clicking first on a parent. But, don't you also need data from the parent - specifically title and can_play? The overall browse media window needs a title, and you can set can_play at the list level so you can just click play once to play all the results. If you don't have the info from the parent, then you don't have a way to pass this overall info back.
I don't think so. The title is basically just "search results" and if you wanna play the list, you can just queue up all list items that have can_play
but if you just passed a parent/child back, then you let the integration set the title, which I might want to set to something more specific - search result for zyz album - but other might not- and yes, you can click each item, but why would you effectively skip functionality which exists in the browser - if you search for something which returns 20 items, having to click each one would be frustrating when it's not necessary elsewhere. You could say the same for a list of tracks rather than a search result, but the can_play is there for a reason. I guess I just don't understand the downside of returning the parent/child when it allows us to pass information that might be used. In the integration, we'll likely be using the same code as we do to build the browse response, so we have it all anyway. In the action, you can just use the children, but if we don't pass back the parent info, we just don't have it for when we might want it.
I am very confused, at what level is a list being returned ?
The action returns a SearchMedia object just like @dry token says he thinks we should do https://github.com/home-assistant/core/blob/dev/homeassistant/components/media_player/__init__.py#L1191
As you say, async_search_media returns SearchMedia, which is
class SearchMedia:
"""Represent search results."""
version: int = field(default=1)
result: list[BrowseMedia]
I guess I think this should be
class SearchMedia:
"""Represent search results."""
version: int = field(default=1)
result: BrowseMedia
and we use the children in BrowseMedia to contain the list of results - i.e. the same way as we use the parent/child relationship in async_browse_media
children: Sequence[BrowseMedia] | None = None,
That would allow us to pass "parent" info back from async_search_media rather than just "child" info.
There's likely nothing useful in the parent info for the action, but it gives us the flexibility in the future.
If there is a specific need for providing search metadata, it should be added to the SearchMedia class
Each class has it's own concerns
the metadata of a search query are not the same as a playable folder/item
but don't they kinda need to be the same if we want to integrate the results of a search into the media browser window at some point? We're already using BrowseMedia objects for the search result items, but if we want to use the overall search results in the future in a media browser window, we'd need all the same data as a "normal" folder so that it can be displayed in the same way. As you say, we could do that by maybe adding another dictionary at that point to the SeachMedia class to allow us to pass back the necessary data, but then we're kinda just recreating everything that's alredy in BrowseMedia.
No we don’t know what we'll need there exactly yet and we’ll add that to SearchMedia as we see fit
One interesting discussion came up recently and that is that we have different media sources
Media players like Sonos or Cast will list media sources that are provided by other integrations
Should we explore how we can allow media sources to offer search ?
For example, the Radio Browser integration would allow to search for radio stations.
👀
@gilded tangle
Sorry that I'm late to the party, but I am just now getting around to implementing the search_media service in my SpotifyPlus (MediaPlayerEntity) integration.
Are there any plans to enhance the async_search_media method to include extra keyword arguments? Kind of like what the play_media method does for ENQUEUE support?
It would be nice to be able to pass some custom keyword arguments to the underlying interface, which is currently not possible with the static SearchMedia parameters. For example:
spotify_limit_total:int- contains the max # of items to return for each type.spotify_market:str- contains an ISO 3166-1 alpha-2 country code. If a country code is specified, only content that is available in that market will be returned.spotify_include_external:str- If "audio" is specified it signals that the client can play externally hosted audio content, and marks the content as playable in the response. By default externally hosted audio content is marked as unplayable in the response.
Example service call:
action: media_player.search_media
data:
entity_id: media_player.spotifyplus_todd_l
search_query: "Beatles"
media_filter_classes:
- album
- artist
- track
spotify_limit_total: 25
spotify_market: ES
spotify_include_external: audio
I could then do something like this in the search_media method to access those parameters:
# get keyword arguments (if any).
spotify_limit_total:str = kwargs.get("spotify_limit_total", None)
spotify_market:str = kwargs.get("spotify_market", None)
spotify_include_external:str = kwargs.get("spotify_include_external", None)
Thoughts?
Yes - I've also made the same request. Since it changes an entity model, I wrote it up as an architecture discussion, with the necessary changes at https://github.com/home-assistant/architecture/discussions/1241 but it hasn't got anywhere.
@dry token Thanks for the architecture discussion link; I added my use case example to it. Hopefully it gains some traction. Your proposed code really is a simple (and elegant) solution to the problem - nice work!
Thanks @trim pike . Yes, I could really do with extras support as well - there are searches you can't do currently which mean people can't migrate off using the native api, which was part of my goal with implement async_search.
I haven't submitted a PR since this is an entity model change so needs an approved architecture discussion, but I don't know anyway to push it forwards, so just been waiting basically.
I wonder if the right approach is to submit the PR and reference the arch discussion, but that seems a bit presumptuous.
I just drafted the PR - https://github.com/home-assistant/core/pull/149961 - tests need updating, but no point in worrying about that until we make some progress on the arch discussion.
Proposed a semi-significant change to the play_media service, would be nice to get any thoughts from some media experts, if this is the right direction to go:
The challenge is that sometimes people do want to enter a normal URL
or they want to enter a deep link they manually crafted
which I guess, could be included in the media browser as a custom mode maybe
hidden behind an overflow menu
I guess there's always yaml mode.
Guess I didn't realize normal urls were even possible there? Thought it had to be a media:// thing.
Depends 😬
But the other day I was like trying to just do a basic thing, like play a song I had in my media folder and it's nearly impossible to figure out what the media_content_id is. The only reason I was even successful was I knew how to hack it out of browser developer-tools 😬 .
Basically, if media source / media browsing is supported, it also supports URLs
as media sources resolve to URLs (which can be local, but don't have to)
Yeah 100% agree
that's why the media selector was updated for media ID in assist_satellite.announce
definitely would be nice to bring this to play_media
so I am with you, but we might miss some
My vision for media source is that it will replace all use cases for local path in core
anytime we allow uploading something, it should be selectable in media browser
Did something recently change on the media browser? The vertical gap is too small
ah looks like the vertical gap changes as the width of the window changes
I think the whole view needs a design review
When I pull up the media browser to select a specific content type (e.g. image), at the root level browse I get non-imagey sources like Radio Browser and TTS. Is there or should there be something to filter out these sources?
Inspecting the websocket response, I don't see anything in the information returned that could tell me about what kind of content I might find in those sources. Every root source child says:
media_class: "app",
media_content_type: "apps",
children_media_class: null
I'm not very clear on how these three keys are expected to be used.
Should something be set in one of these to indicate that this particular source has only a certain type, e.g. audio?
I think I'm confused between a media_class and a content_type. Are they explained on any of the dev docs?
children_media_class wouldn't be a way to represent that?