JAMS Technical Discussion

haha. Happy to have such good apps inspiring such thinking!

Really is great to see, @Nigel, @BryanB!

Keep up the good work :tada:

1 Like

Correct, in the same way as when you change a file of a safesite, everyone sees the change automatically.

I’m not sure I understand what you mean, but I think I know were you are coming from. One important thing to remember is that the account’s Default Containers (i.e. _public, _publicNames, etc.) are just private MutableData, i.e. they are not stored in a specific or special place, they are just at a random location and encrypted with the account’s/user’s credentials. What makes them special, if you wish, it’s just that you have an index created by default (in the Root Container) when the account is created so you can access them thru their names. You can find more details about the Root and Default containers in this RFC: https://github.com/maidsafe/rfcs/blob/master/text/0046-new-auth-flow/containers.md

I think that’s what the type tag is/should be for, so you can have a convention of type tags for albums, another for playlist, etc.
Also, if you think about it, you could be publishing albums using their title/name in a similar way as how the public id’s Services container are stored. Thus if your album is called "Soda Stereo" and the convention for albums is to have a type tag 15008, the album’s MD could then be stored at address sha3("Soda Stereo") with type tag 15008, then I don’t even need to give you the XOR address to share it, I just text you with the album’s name. This will only work if that address happens to be free obviously, perhaps unlikely to happen but totally possible (you could have some squatting issue here as well I imagine).


This is an interesting thread and very useful in trying to figure out the best design patterns to use with the SAFE API and storage model.

A couple of thoughts:

This is tricky. One thought is where individuals share things the app creates a ‘salt’ for each user, and when sharing with trusted friends this ‘salt’ could be shared. So users of hash(title) the xor address to find things I share with you would be hash(title) ^ happybeing's salt

Clunky, the salts would be stored by your app, so if @bochaco texts me Hey happybeing, check out ‘Soda Stereo’ I paste ‘Soda Stereo’ into JAMS and when it comes up with not found it prompts Check friend uploads? and when I choose @bochaco from the list it can find the file by using his ‘salt’.

Ugly, so maybe not a great idea. Into thought number two…

To handle the problem of Gabriel sharing a playlist with me or anything else with editable data (music library index) there are two options, and apps can do either A or B, or offer this as a configuration setting, or prompt etc

A) Store a pointer to the Mutable Data. Pro: simple, cheap (1 PUT) Concensus: when Gabriel changes his MD I might lose stuff I wanted to keep (eg a particular music file) or worse, be deceived into downloading something harmful (malware, porn, an advert for Coka Cola etc)

B) Store a Copy of The Mutable Data, including a pointer back to the original). Pro: I have both the original and my own copy which I can edit Con: it could cost more (depends on the size of the index).

C) Store a Copy of the Mutable Data in an Immutable Data, and add a mutable data if I ever want an edited version (which could just store changes). Pro: maximum functionality - never lose the original, can see/track Gabriel’s changes, can have my own changes on top of the original or in top of Gabriel’s latest. Con: more complexity, cost depends because using Immutable Data might be cheaper than B) until you start editing at least.


Those options you described @happybeing is exactly what I had in my head, just give the option to the user receiving a shared album/playlist, because sometimes you are sharing an album with someone and he is not really interested in storing a copy/clone of it but just listen to it once, the same for those using a jamstube safesite :stuck_out_tongue: , the user could be just drinking some beer while listening to random music that was shared by people and friends, perhaps when the user likes a song/album/playlist (by clicking a like button/icon) at that moment the app can make a copy/clone for the user (option A or B).
I agree this is a nice topic with interesting thoughts!


Hmmm. I’m not sure the type tag is necessarily enough… Or I worry things could get too granular there (and we end up maintaining an index of type tags to find all relevant to your cause…)

A playlist could be music or video… or audiobooks… (or a specific subset of those).

A playlist type tag doesn’t necessarily help an app distinguish if it’s what it should be consuming. So then would we have a type tag for each? Or is an ‘indexed list’ the type tag (and so would be applicable to search indexes as well) and then some ‘tag’ setup on the data which could be used in terms of metadata searching.


@joshuef this is where I’m trying to feel my way towards how / when to use services. With a service* you can provide behaviour as well as type, and both can be modified and extended in a back compatible way, similar to an API.

* With apps using services implemented using a library that is, which is what I’m currently exploring in this topic and the safenetwork-webapi library.

If anyone has thoughts on those I’d be very interested as I’m going out on a limb at the moment.

I’m not coding this week but will get back to it after the weekend and fingers crossed a demo is not far off.

1 Like

@happybeing, your link to the library doesn’t work. :frowning: (you’ve capital .JS at the end)

having a look the now :+1:

1 Like


Good thought, and don’t worrying about interjecting. This is a pretty open thread and your comment fits well.

So the history itself might not be a service as we’ve been discussing it, but making one’s history public could allow it to be mined by recommendation services on behalf of the user or other users who share similar tastes.

in fact, the same could be said for your history or a carefully crafted playlist. Fun fact about JAMS: History is just another playlist. So generally, make playlists publicly available for mining (ideally at the user request and not be default).

I’ll keep that in mind and add it to notes for future work.


I didn’t mean to imply that. I meant to imply that as JAMS uses the data now, it is a list of XORs without context. The context is assumed by JAMS, if you loaded a list of XORs that weren’t songs … it’d get dumb about it and treat them as songs anyway.

I agree that an abstract data structure would be nice. Perhaps a UUID (or a subset of UUID to reduce bytes) to identify data types could be employed? Maybe build a registry so humans can look it up and understand what UUID is reserved for what data types? Potentially include a version as well, though honestly, UUIDs are large enough to have a new one for each new version.

For example, there might be a UUID for Type: Song, then another UUID for Type: Indexed List. Each item in the Indexed List is a tuple of (UUID, XOR). Now JAMS can load a playlist (which is an Indexed List) and check that each XOR corresponds to a song type that JAMS understands how to parse by checking its corresponding UUID. JAMS no longer would assume each XOR is a song, and should not-a-song be encountered, it could easily decide this isn’t a valid playlist for JAMS.

Copy/Paste and replace “XOR” with “MD url”, or have UUIDs which refer to XORs and others which refer to MD urls, then the second part of the tuples might contain XOR or MD url. Shrug. UUIDs are huge.

EDIT: I’m responding to comments in order, and I see these ideas are being hashed out in a number of ways after I already wrote this response here. This response still seems valid for quite a bit of different comments from @joshuaef @happybeing and @bochaco



I looked so many places for what type tag means and what values to use. All the documentation had examples with arbitrary numbers (and no description of what the field is used for at all), so I began using the arbitrary numbers from the examples.

Is there going to be a list of accepted tags chosen by the community somewhere? Like a wiki or a registry? I’m not sure having every developer wing it is a good idea.

Is there any network advantage to using type tags instead of baking it into the (higher level) data of the MD or XOR? Why would someone use a type tag other than it’s there?


Possibly an off topic but, have you considered adding a lossless audio format? For any audiophile it is a very important option.

The most common lossless format is Flac and you have JS libraries like https://github.com/audiocogs/flac.js


Also Ogg Vorbis support :slight_smile:
(The FLOSS version of mp3)


Not sure how applicable in this context, but in case it is, the semantic Web provides a universal mechanism for identifying data types, creating /finding & re-using vocabularies etc based on URIs rather than UUIDs, so when apps use those there’s a greater chance of cross app data sharing, data discovery etc. I don’t know a lot about this yet, but if it is applicable here I think it might be worth investigation.

1 Like

I modified an HTML5 audio test page to work on Safe and both, Peruse 0.4.1 and SafeBrowser 0.9.0, pass all the test including ogg, opus and flac.



@drehb @digipl

We’re currently using the built-in AUDIO tag. The browser handles which audio formats are supported. However, I’m fairly sure the Safe Browser is built using FFMPEG which should support FLAC and OGG. Try it out!

I’m uncertain about the streaming browser and how the streaming will integrate with the built-in audio support. That’s a different issue for a different day. I’m also uncertain if the Peruse browser is built with the same audio parsing libraries, but I’ll test that out soon enough.


One of these days I’ll read all replies before posting responses. Today was not that day. Thanks for the thorough testing! Also glad to hear it’s working with Peruse, I hadn’t gotten that far yet!


I only have limited metadata parsing support. I can read ID3s off MP3s and I think whatever metadata from AAC. This is from an open source javascript library. It doesn’t support metadata from other audio containers like OGG. So if you upload a song in a container like OGG, I strongly suspect you’ll have to fill in the artist, song name, and album yourself. I haven’t found many open source Javascript libraries to parse audio files as it is, so I was happy we got the two most common formats covered.


I appreciate the sentiment, but semantic web is very pie-in-the-sky, and I’m effectively trying to engineer something today, right now. If we can find concrete, solid practices that are proven today, great! If not, then I’ll wing it or use other practices (like UUID which are tested and proven and in common use). This project is more about getting it out there than getting it perfect.

I am both an engineer and an academic (which is why I appreciate the note), but as a lone developer on this major project built atop bleeding edge software with a lot of quirks, I am strictly an engineer or the project would never move forward.

I’m not sure why you are so skeptical about the semantic Web, it exists and is ready for anyone to use - I’m not sure if it is applicable to JAMS, but there’s very little overhead in finding out if there is a suitable RDF type - which I’d be happy to help with. Adopting that rather than a UUID that is known only to your application would I think be trivial. Adopting RDF would be more work, so of course you may not feel it worthwhile, but there are potential advantages for applications and there are lots of libraries ready to use, and a community of developers to help anyone trying to use them.

LinkedData vocabularies exist ready for use and are being adopted widely. There’s a decent and growing set of tools in use and many in development. Add that to LDP and you have something much more than a single application with application specific data, and interoperability with a growing ecosystem.

I get that you don’t want to be diverted, so no problem with that. Just want to correct the impressions about the state of LinkedData / RDF, and to let you know that I’ll help where I can.

EDIT: I did a quick search…

This gives a basic intro to using RDF for audio publishing:



Did you check this?

Or this?


The word “ontology” is what makes me skeptical. Great for academic studies and planning out solutions, but I’ve not yet seen RDF implemented by anyone trying to accomplish anything. It’s usually an academic research tool, which is valuable, but not for getting stuff done. Almost every RDF I’ve seen people promote gets set aside for a W3C or IEEE RFC that solve the problem in a more compact and elegant way. My experiences with RDFs is that they are usually too abstract to be of practical use, and any implementation details effectively make it your own version separate from the “specification.” Things might have changed since I last looked though. Again, I’m trying to get the app done, not research abstract ontologies (which is a fun pursuit, just not for this task).

I’m glad to see really good documentation here. I don’t see it as a widely adopted standard though. If you see this being used in the wild and see how it applies to JAMS interoperating with those wild applications, I’ll consider overhauling all my data storage at that time.

It wouldn’t necessarily be restricted to JAMS, especially if the UUID scheme is well documented and shared. Just like the RDF you pointed out. Adoption is what matters. Given all else equal, I’d rather get it done quickly whipping together a UUID solution than spend weeks trying to grok the ontology of the RDF. Can always go back and change it later.

1 Like


Thanks for doing some research.

Borewit’s music-metadata is for Node, which uses a different Javascript engine. It’s meant for server side JS interpreted by the Node engine. We’re using client side JS interpreted by the V8 engine.

Most of what I found on github was for Node.

Tmont’s audio-metadata is something I will bookmark and look at more closely. Based on my quick look, I think it only supports OGG and ID3 (and I already have ID3 support). The addition of OGG is certainly something.

1 Like