I have multiple notes with metadata (YAML tags) and each note corresponds to a single mp3 file. Both the note and the mp3 have the same name. I’d like to dataview/dataviewjs/query a directory of notes and then based on the metadata have those mp3’s listed as playable files in the page.
I can get this to work with images but not mp3s.
Things I have tried
I can have an mp3 playable if I manually type it, like this
![[song.mp3]]
I can also use dataview to grab images from notes and display those using the embed(link), like this
LIST embed(link(file.name + ".jpg"))
FROM ("dir1" or "dir2") and #tagA/subtag
sort file.name asc
But when I try to use technique #2 with .mp3s, it doesn’t work.
It just lists the results as text. Perhaps this is a feature request for dataview development. I already put in a request here.
But I’m curious if anyone has a workaround, especially with query or dataviewjs.
I searched for mp3, embed, didn’t find anything regarding this.
Your solution does give me a list of mp3 files, but it doesn’t fix my main issue; I’d like a page with all the queried songs embedded. (see image below)
Other goals:
The obsidian media player doesn’t play the next song on the page, it just stops after the first song. But I’ll deal with that issue next.
I’d want to use dataviewjs to randomize the song list order.
The end result would be a way to generate randomized, dynamic playlists based on metadata.
Yeah, and it opens playback up in a popup that disappears if you move your mouse.
I’m interested in this too.
I thought I had opened up a feature request to show the name of mp3 attachments above the attachment, but I can’t find it. That’s the minimum I’m hoping for, but I’d love your solution too!
I think the way forward would be to use a combination of Buttons + Templater + Dataview. The gist of the idea is as follows:
On a given page, have a button which replaces all text after the button with the result from a Templater command
The Templater command (based upon a template) triggers a Dataview script which collates the mp3-files in a random order using markdown syntax, which the template appends to the current file
This will give a static version of the embedded files, which will circumvent the issues that Dataview has with embedding files, whilst still allowing for a refresh of the playlist by the hit of a button.
Is this idea something you’re able to implement yourself? I’m running a little low on time tonight, so I need to do something else. If you’re not able to do it yourself, I might look into it one of the next few days.
Thank you for your reply! I’ll try Krakor’s dataview implementation first. I’m not a programmer, so your suggestion is beyond me. Let me test and report back.
However, I did run into some issues if you have time to point me in the right direction.
I think the playback controls are missing. I saw reference to them in the view.js, but they aren’t showing up for me. Any ideas?
The top left icon opens up youtube to the default page. If I want to remove that icon, since I don’t need it, is there a way to do that in the view.js?
Same for the top right icon (and bottom icon), which just give me an error. I’m not sure what they are trying to do anyway.
In the mean time, I’ll read through your documentation again and see if I can figure it out.
Thanks again, this is a great setup! Works perfectly on mobile too.
Thank you for the review, I’m really glad to hear that it meets your needs
However, the screenshot you showed looks very weird, like the css is not working at all…
Did you copy the view.css file from the repository and put it in the same folder as the view.js file?
To answer your questions:
The readme controls should display correctly with the css. I added an image in the readme to show how it should look like
For your second question, if the css was working correctly, the icons would not be displayed in the first place because the thumbnail behavior “override” them.
However if you don’t have the THUMBNAIL_IS_URL_LINK constant set to true, you could set HIDE_ICONS to true in the view.js to hide them
And for your last point, you could add the disable string “addscore” in your codeblock to remove the + button at the top and bottom of the grid.
That make me think that it would be nice to add a global disable constant option in the view.js to have it applied globally. I’ll consider adding that at some point.
Also, you made me realize that I didn’t specify what these buttons do in the readme, so I added an explanation.
I was expecting you to ask this question, but unfortunately it is not easily achievable at this time. I would have loved to implement a natural language to do it like you showed but I don’t have the same ambitions as Dataview and it would have been way too much work to implement my own DSL parser in pure javascript just for this use case.
Anyway, what you could do is use the function filter option to filter manually with your custom logic. Note that I have not yet documented the query.js file or provided examples on how to use it. But here is how to write the OR logic for your examples:
Thank you, I think this should still be ok for my purposes. Is there a straight forward way to make it take N number of tags? I tested a couple ways but none of them worked.
await dv.view("_js/jukebox", {
filter: (qs) => {
const from = '#🎼 AND "jukebox/songs"'
const tagA = qs.from(from)
.withTags("#music/rockA")
._pages
const tagB = qs.from(from)
.withTags("#music/rockB")
._pages
const tagC = qs.from(from)
.withTags("#music/rockC")
._pages
// Combine two tags (works)
//qs.setPages(qs.joinPages(tagA, tagB))
// Combine three or more tags
// Test 1
//qs.setPages(qs.joinPages(qs.joinPages(tagA, tagB), tagC))
// Test 2
//const tmpA = qs.joinPages(tagA, tagB)
//qs.setPages(qs.joinPages(tmpA, tagC))
// Filter with tagC
//.withTags("#tagD")
},
sort: { shuffle: true },
disable: "addscore"
})
Also, regarding your jukebox in general, is this something you’d be ok with me sharing in another thread? I think it is useful and other people would probably appreciate it. But if you were planning to roll it out, I’d defer to your timeline for that.
To explain briefly, this is because this function expects a Dataview array as input but the array returned by this function is not a Dataview array.
I’ve just pushed a new query.js to make this function a variadic one (that means it can take as many params as you want) and also to support non dataview array in entry.
So both your tests should work but it would be easier to do qs.joinPages(a,b,c)
If by another thread you mean a whole new thread to present the view, then I’d prefer to do that. But first, I’d like to remove every opinionated features in it before sharing it (I’m thinking about the file creation button that auto populate some of my own fields).
I don’t have much time right now to do that but when it will be done, I’ll share it properly.
But if you plan to mention it in another existing thread to help people, then sure, feel free to do it.
Thanks for the explanation. Just tested and it’s working great! I’ll use the simpler joinPage(a,b,c) going forward.
I’m glad I asked. I won’t start a new thread and will wait for you to roll it out when you’re ready. In the mean time, if it comes up in conversation I’ll just point people to this thread.
And thanks again for all the help. This new music setup has improved my quality of life, I really appreciate that.