Giter VIP home page Giter VIP logo

jellyfin-meta's Introduction

Jellyfin Meta

Part of the Jellyfin Project


Logo Banner

Donate Feature Requests Chat on Matrix Join our Subreddit


Jellyfin Meta hosts discussion topics across multiple repostories, for instance tracking release issues, discussing new wide-ranging features that affect multiple sub-projects, etc. Discussions meant for individual projects are hosted inside their respective repositories.

jellyfin-meta's People

Contributors

anthonylavado avatar bond-009 avatar heyhippari avatar joshuaboniface avatar nielsvanvelzen avatar shadowghost avatar thornbill avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jellyfin-meta's Issues

Library database EFCore migration and API v2 discussion

We've had this chat in Matrix a few times in the past and it came up again yesterday (I poked the bear I know), so I figure it would be prudent to get an actual meta issue going about how to approach this.

To recap the current situation:

  • All except one backend databases have been migrated to EFCore with minimal schema modification.
  • The "library.db" backend is currently the last one waiting for this migration.
  • The current library backend is split between SQLite (in library.db the file) and XML data within the Jellyfin data directory.
  • The frontend API ties very closely with the database functions (note: I have not verified this myself, this is my recollection of how it worked from those more knowledgeable than me).

This means that, to complete EF Core migrations and enable external database support (a very much-requested feature) and everything that provides (load balanced instances, failover, easy backup/restore, etc.), the library database must be ported into EFCore somehow.

For the finished migrations, @barronpm has been driving that project, but I know he has not had much free time to contribute recently, so for the most part work on this has stalled somewhat.

I'd like a 10.9.0 goal to be "finish the EF Core migration", so we could enable that feature for users sooner rather than later.

However this ties into our long-running "API v2" discussion, which in the past has had some strong opinions. So I figure I should outline what I think the options are and solicit feedback from the major stakeholders in @jellyfin/server.


The main reason for debate is because of general dissatisfaction within the project about the current Emby-inherited API (a.k.a. the "v1 API"). It has several limitations, doesn't make much sense in some places, has little organization, etc. So, from very early on in the project, there has been much talk about designing a better, more robust and extensible v2 API.

And because of how closely the API and the database backend are tied together, the plan here ties directly into the database migration.

As I see it from my minimal in-depth code knowledge and perspective primarily as a user and project manager, I see 3 real ways this can go.

  1. We migrate the current database schema - warts and all - as much as possible into EFCore - depositing the XML right into DB rows instead of onto the filesystem, keeping the current SQLite schema functionally unchanged, etc. We make no code changes to the API functions whatsoever except what's needed to move "look up data from file on filesystem" to "look up data from table row in database".

Pros: We completely decouple any "v2 API" discussions from the EFCore migration today; we get the "multiple backend databases option" finished and out to users much more quickly; minimal functional code changes (no new functions, etc.).
Cons: We're stuck with the current schema - warts and all - with EFCore; we have weird XML in the database (it's better than binary data at least) or we somehow translate this sensibly into new tables only.

  1. We make functional improvements and modifications to the schema and port it into EFCore. This would change the functional schema of the database and would require some additional functions or changes to functions, up to and including translation wrappers, in order to preserve the current API exactly as it is.

Pros: This gets us what we want in terms of the database (better schema) while also preserving the API so that it actually gets done; we have a flexible foundation and could write a v2 API in a leisurely pace by leveraging the wrappers or the backend functions directly.
Cons: More code changes right now; have to agree on the schema.

  1. We tie EFCore and a v2 API completely together, with the former depending on the latter.

Pros: Everything is nice and clean at the end and during transition.
Cons: Indefinite transition state during which EFCore migration is not complete; requires us to actually make an API v2 first; lots of code changes at once to implement both the EFCore library backend and the new API frontend; introducing a v2 API can't be done peacemeal and must be feature complete before released to the world along with transition time for clients and 3rd party integrations.


Now, I know the consensus seemed to always be on 3, but I don't think that's a sane way to move forward. There was talk of freezing current master for some indetermine time while this was worked on, and I've always fundamentally disagreed with that since it's effectively killing "Jellyfin" development as it exists today in favour of a functional rewrite of half the server code just to get a new database backend, which seems very excessive and user-unfiendly to me (no new features, bugfixes, etc. for possibly years, if it even happens at all). And as I've mentioned briefly above, no one externally is really asking for a "v2 API", so I'm not sure killing active development for that is really worthwhile. IF someone wants to do it, that's fine, but at that point it would really have to be a hard fork while the work is done (and this is what was basically proposed when this was last discussed).

That leaves the other options: 1 seems like the "simple" option, and while it means a bit of ugly code and ugly database tables, it gets the EFCore migration done and out of the way. 2 seems like the better, more robust solution, as it sets us up for a v2 "some day" while preserving the v1 API as it currently stands. What I don't really know is what the comparative work effort of either is. If 2 is not much worse than 1, we should really take that route IMO, otherwise we just do 1 and accept the bad DB, then worry about a better DB whenever we actually do the API rewrite.

So, open to thoughts and constructive criticism. Anything I missed, etc. It is ultimately up to the stakeholders how to proceed, but I stand my by recommendations here as the most healthy for the project.

Add custom scheme handler / intent handler to accomodate single-sign-on via browser

Request

Basically, I'd like to be able to open a link with a custom schema to the app that supplies:

- serverUrl
- userId
- accessToken

To an intent handler (or whatever we call it in ios), that stores that information in the web client to initiate a session, and skips the login.

This would intend to accomodate single-sign-on via plugin, eg the popular

https://github.com/9p4/jellyfin-plugin-sso

Here is a demonstration of the current flow on the android client (behaves similarly)

Screen_Recording_20220717-200505_Firefox.Beta.mp4

Take note that although we can get a via single sign on, the new session is in the browser, rather than the jellyfin app.

From a technical perspective, this is not too hard to implement, both Android and iOS have APIs for using custom links open apps with some kind of data payload https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app

Background

I am one of the maintainers of a plugin that provides single-sign-on to jellyfin servers

https://github.com/9p4/jellyfin-plugin-sso

The plugin is now at a stage of development where its functionality is quite mature, but its main limitation is that it only supports the web-client.

Flows

Assume the jellyfin server lives at https://myjellyfin.com

The plugin can serve a page that initiates the SSO flow (either oauth or saml, I'm mainly going to talk about oauth), this page is at https://myjellyfin.com/SSO/OID/p/<provider_name>.

The plugin also serves a callback page for completing SSO flows, eg https://myjellyfin.com/SSO/OID/r/<provider_name>.

For example, you might use Google as your provider, so you'd use https://myjellyfin.com/SSO/OID/p/google, and https://myjellyfin.com/SSO/OID/r/google

On the web-client, the SSO flow from login-page to signed in dashboard is straightforward.

User perspective (Web client):

  1. On the login page, not signed in
  2. Click on the link to "Sign in via SSO"
    • Get redirected to the sign in-page for your SSO provider (eg, google)
    • complete the flow on your SSO provider (eg, confirm sign-in, or select your account)
    • get redirected back to jellyfin, and you're signed in

Actual flow (Web client)

  1. User on the login page, not signed in
  2. User click on the link to "Sign in via SSO"
  3. (OAuth magic) This takes user to a page (https://myjellyfin.com/SSO/OID/p/google with a javascript client that initiates an OAuth flow
    1. The js client redirects the user to https://accounts.google.com/o/oauth2/v2/auth
      • The user completes the prompt on google
    2. Google redirects to https://myjellyfin.com/SSO/OID/r/google with the oauth state required
  4. On the redirect page, a js client uses the state given by google to confirm a valid session with the jellyfin server
    • The server gives the client a user ID + authorization token
    • THe client stores this in localStorage, with enough information for the browser to now have a valid, logged in session
    • The client redirects back to the homepage, (https://myjellyfin.com) and is now logged in

This flow works reliably. An important note, however, is that a lot of the oauth client-handling is done using javascript clients in web pages server directly by the plugin.

Limitations

Because the above flow relies on a browser oauth client, it effectively establishes a valid session within the browser

https://github.com/9p4/jellyfin-plugin-sso/blob/fad5a62e07e44c84bc94d5962b8b79e80c102ee8/SSO-Auth/WebResponse.cs#L449-L458

    var responseJson = JSON.parse(response);
    var userId = 'user-' + responseJson['User']['Id'] + '-' + responseJson['User']['ServerId'];
    responseJson['User']['EnableAutoLogin'] = true;
    localStorage.setItem(userId, JSON.stringify(responseJson['User']));
    var jfCreds = JSON.parse(localStorage.getItem('jellyfin_credentials'));
    jfCreds['Servers'][0]['AccessToken'] = responseJson['AccessToken'];
    jfCreds['Servers'][0]['UserId'] = responseJson['User']['Id'];
    localStorage.setItem('jellyfin_credentials', JSON.stringify(jfCreds));
    localStorage.setItem('enableAutoLogin', 'true');
    window.location.replace('" + baseUrl + @"');

It literally stores all the state the web-app needs in order to resume a session.

The problem is, that we can't use this to log-into the android or ios app

Additional context

Discussion migrated from Matrix - Pretty long but included for posterity

Matthew Strasiotto: (July 6ish)

question -
Is it at all possible to add an intent to the jf android app that signs onto a user account using a token generated from elsewhere?
i'm reading about SSO for android, and how to add SSO clients to android apps
https://github.com/openid/AppAuth-Android

i'm a contributor to https://github.com/9p4/jellyfin-plugin-sso
the actual oauth client works on jellyfin-web, & i'd like to get it to work for the android client -
The best way to do that is probably something along the lines of AppAuth-Android / maybe intent filters

in reality, as long as we can trigger some kind of redirect back to the jellyfin app with enough data from the authenticated web-session to get a user logged into the app, there isn't a tonne of work

...

Matthew Strasiottio:

mcarlton
Matthew Strasiotto

would quick connect accomplish what you're looking for? i'm not sure if it can be used in the android app as a client side yet

Quick connect is good, and a good workaround for the use-case where people's primary authentication is SSO
It does work on the android app, but the limitation is that the current SSO flow my plugin gives will basically Auth a session in the browser, and a user would need to

  1. Initiate browser SSO
  2. Swap back to jellyfin, initiate quick connect
  3. Swap back to browser, complete quick connect flow

Pretty clunky, good for Auth across devices tho

Matthew Strasiotto July 17:

I'd like to support the SSO plugin i contribute to in jellyfin-android & jellyfin-expo
I've heard from maintainers that they're not interested in supporting SSO in their apps at this stage as it would require each client implement it.
I'd like to get around that with fully browser/web-app based implementation that's handled by the plugin, which basically handles the flow, gets the userID + access token

The browser client would then open a custom scheme link that passes the server ID, user ID & access token back to the app, and triggers a "sign on" intent

for either case, the jellyfin-android + jellyfin-expo app would only have to handle an intent being given with fully-formed credentials, and everything else could defer back to their web wrappers.

Before i commence work on this, I'm curious if maintainers are open to considering PRs on either project (jf-android / jf-expo) that allow custom URL scheme handling for the scope of "given serverID, userID & accessToken, initate a session then commence main activity" so that my plugin can handle the rest from a native browser

image

image

image

July 21

https://matrix.to/#/!YOoxJKhsHoXZiIHyBG:matrix.org/$qn4tvt0GXVlDnBYIGgM0wCuO0C2SO2AAUyAI9xiQHlc?via=bonifacelabs.ca&via=t2bot.io&via=matrix.org

image

image

image

Reconsider supported media types

Currently Jellyfin has support for 9 different content types (not counting trailers, boxsets and playlists), with the majority being in pretty bad state usability wise. In my opinion we should reduce our feature set so effort can be focused on our core features (as we have done in the past, e.g. removing Game support) More specifically this would help the EF Core database migration as we would have less entities and abstractions around different media types to worry about. (jellyfin/jellyfin#2518 for example)

Current content types:
Core features:

  • Movies
  • TV Shows
  • Music
  • Live TV/DVR

Heavily related to core feaures:

  • Music Videos

Remaining:

  • Home Videos
  • AudioBooks
  • Photos
  • Books/comics

I propose be remove some of the "remaining" content types, starting from the bottom as those share the least amount of code with other media types.

Looking for feedback: Is there a need for a test-library generator?

Motivation

To troubleshoot a bug, I just had the need for a large media library of an item type I don't use, so I wrote a quick python script that creates a fake library. I now wonder whether I should develop this into a small utility that can generate libraries for all item types. Is there a need for this / would it be helpful for your development workflow?

Proposed approach

Prepare lists of plausible items of each item type

  • E.g. random 1000 songs taken from MusicBrainz, Movies from TMDB, etc.
  • One video and audio file as placeholder for the actual content

Then have the script use the lists to:

  • Create appropriate folder structures for the item type
  • Sym- or Hard-link each item's media file to the single placeholder
    • Hard-links would be necessary for using the library via bind-mount in a docker container
  • Create appropriate .nfo files for the importer to pick up the linked files
  • Fix up possible required additional changes via the API
    • Music requires artists to be set on the song for which no .nfo files can be written

Support reading port from SRV DNS record

Is your feature request related to a problem? Please describe.
Login flow for servers using HTTPS with a non-default Jellyfin port is terrible, even when selecting a server from a local network.
Having to type in the whole https://jellyfin.example.com:443 for connections is a terrible UX, especially on a TV where input is already painful.

When selecting from the list of servers on the local network it will just throw up an error that it can't connect to port 8096 on the server, which yeah I'm not using that port... How is it finding the server, but also not able to read the port its running on?

If I leave off the https:// and just do jellyfin.example.com:443, I get Error: [-3] as the message with no other explanation. The only thing I can assume here is that it is defaulting to HTTP over this port which will never reach my server since HTTP traffic is not being accepted on port 443 in my gateway.

Describe the solution you'd like
If I could just type in jellyfin.example.com and have that be enough it would make the experience a lot better.
One way to do this would be supporting SRV records on the domain, for example something like this would be what it would look like in Cloudflare:
image

Reading the port from the DNS record there makes the process a lot more simple to the end user, though it would be an extra (optional) step for the person setting up the Jellyfin server.

As for the HTTP/HTTPS issue, would it be possible to check if HTTPS is supported and if not fall back to HTTP for the connection?

Describe alternatives you've considered
I could just port forward those default 8096/8920 ports, but I don't want to do that.

For me my network goes:
Internet ---> Router ---ports 80/443---> Nginx Gateway ---depending on the subdomain---> Application VM

So if I forwarded those ports directly to the Jellyfin server it would bypass the Nginx Gateway I have setup and leave my network slightly less secure since the traffic wouldn't be going through the firewall I have configured there.

Additional context
Ports configured in the Jellyfin network settings:
image

image

Project-wide error reporting solution

This has been the subject of (very heated) team discussions before, but I would like to officially bring it to the table in a public fashion, as I feel this is an important thing for client quality going forwards, especially with things like Roku, WebOS, etc.

The problem

Some of our clients don't have facilities for error reporting or getting logs. The biggest offenders are, of course, TV-based clients (Roku, WebOS, Tizen, etc).

This can lead to both quality issues and frustrations for both developers and users:

  • It's hard to debug those platforms.
  • Users often don't know how to debug those platforms, needing to make custom builds or enable developer options, setup SDKs and whatnot.
  • Developers have to spend a lot of time guiding users to help them get proper debugging information
  • Issues are often lackluster in information density and quality for bugs, leading to them being mostly ignored because impossible to reproduce.

In a more general sense, the quality of the majority of issues has been lackluster, with no/wrong logs attached, lacking information, etc. This makes it difficult to figure out duplicates, properly triage and, most importantly, fix them.

The current state of things

At least Android TV is using a custom solution for crash reporting already (Seemingly ACRA?) (Which I think is enabled by default, looking at the code, but I'm not an Android user or developer, so this might be wrong It is in fact opt-in, my bad).

This leaves some parts of the project in a weird spot: we don't have a way to get errors or crashes, and each client would have to roll its own solution if we want that (For example, we've made an on-screen developer console for WebOS before).

In my opinion, this is sub-optimal for a few reasons:

  • It leads to more infrastructure
    If every project rolls with their own platform or way of doing things, we may quickly end up with 5-6 different error reporting solutions or ways of getting proper reports.
  • It's a bad user experience
    If a user reports a bug and we spend 6 hours getting them to install a WebOS SDK, setup Node.js, enable the on-screen console and building+deploying the clients, it's a bad experience for everybody involved
  • Software quality suffers
    Without a good way of getting error reports, we'll constantly have quality issues. Stuff will break, users will be angry, we'll be frustrated and, in general, the project will be worse for it. Yes, GitHub issues exist. No, most people will never fill a GitHub issue properly, or even at all.

The proposed solution

I have pushed this a lot internally, across a lot of very heated discussions, but I still think having a project-wide error reporting solution would be a great benefit to the project as a whole.

One idea was to add an API endpoint to allow clients to report errors to the server. As was discussed on team channels, and agreed with by a lot of team members, this is an impractical solution for a few reasons:

  • It's not the server's job to handle client errors
  • It still puts the onus of error reporting on the server admin. We'd like to avoid that, because users may not always be admins or even have regular/cooperating admins
  • A large number of clients reporting a lot of errors could bring the server down or impact performance

So, essentially, that solution doesn't solve any of the parts of the problems, along with seeming a bit half-assed and suboptimal.

The best solution, in my opinion, would be to adopt a proven error-reporting framework, such as Sentry or GlitchTip (Note: there might be other platforms/frameworks and this isn't an endorsement of either).

This gives us one thing to keep track of in the entire project, no matter the client or the technology (At least both of the above solutions use the open source Sentry reporters, and are available for pretty much everything, or fairly easy to implement if they're not).

The raised issues

During internal discussions, a few issues were raised about this proposal:

Privacy

Obviously, one of our strong points is that we don't have centralized infrastructure and don't phone back home (At least in a way that can't be disabled. See plugins as an example of us having a centralized service that phones back to us, which users can disable).

Concern was raised that error/crash reporting would be seen as invading privacy and going against one of our main goals.

I think this is seeing the issue in a very narrow way. Not all crash reporting is negative or invades privacy. We can easily sidestep the "no phoning home" issue by making it opt-in (if this is really something the community at large cares about).

I would wager most people have no issues with crash reporting if it is done in a transparent, non-invasive way, and it opt-in instead of opt-out (But even then, Android TV's crash reporting seems to be opt-out, and we have had exactly 0 complaints against that, including in the team Android TV is opt-in).

More infrastructure

Yes, this would probably require some amount of work from the team members handling infrastructure, if we go with the preferred self-hosting route.

I would argue that the benefit outweighs it, and I don't think our infra is really a large amount of work at the moment, for the most part.

We don't run a lot currently. Essentially (if I'm not missing anything):

  • Our website is hosted by Github Pages
  • So is our documentation
  • We host Mirrorbits and a few file servers around the world
  • We host Weblate
  • We host Feathub
  • We have a reverse proxy for all of it

I don't think it'd be too much to add one more thing to it, especially since it brings a lot of potential improvements to the project. Other open source projects of our size have a lot more infrastructure than we do, and do just fine.

Conclusion

A project-wide crash reporting solution would be a net benefit for both users and contributors/team members. It has the potential to improve our client quality, reduce user friction, improve the quality of issues/bug reports and help with triage (which has been a sore issue lately).

Valid issues were raised, which warrant a wider discussion and, while the project leader was strongly opposed to this, I really think it would be a bad call for the project in the mid-to-long term to be so strict about this.

I would like to ask for comments from both the team at large, and our community (both users and contributors), and push this discussion forward a bit.

Create a Jellyfin artwork repository

For 2 years now, we've still been using the Emby resources repository for some artwork for Studios.

With jellyfin/jellyfin#5009, this provider is exposed as a plugin and the URL to said repository can be changed. This puts us to a place where we can finally get rid of the dependency to Emby and host our own repository, as well a define a structure so others can do the same (In accordance with the project's goal of allowing people to spin up their own instances of anything we host, so they don't have to rely on us).

We currently only support Studios, but the following types could potentially be supported easily:

  • Studios (Technically also Networks and Music Label currently. Hopefully we split these for Jellyfin 11.)
  • Genres
  • Music Genres

In addition, it'd be nice to provide a unified set of TV station icons at a later date, in order to make the entire Live TV experience nicer to look at (See known issues about black logos on black backgrounds for an example of what improvements could be made).

Some early goals:

  • Easy to contribute to
    This repository of images would live through user contributions, in accordance with how the rest of the project works. As such, there has to be a Github repository for it. Maybe we could setup a Github Action to push every PR merged to https://artwork.jellyfin.org
  • Organized
    With a potentially high number of files, it's important to define a structure early on. The one Emby uses isn't bad, but may not be ideal. Do we want to change it?
  • Inviting
    To make adding new resources easy, we should provide thorough contributions guidelines, as well as a simple tool or script to edit the manifest (Even if it's just a list of files) and templates for ensuring a unified and consistent style
  • Support the full "main" artwork range: Primary, Thumb, Backdrop and Logo
    These give more freedom to clients as to how they want to present information and use artwork in their designs.

Ideas for a Test Media Library

This is a quick dump based on a Matrix session...

Goal
Create a media library that can be used for testing Jellyfin in a repeatable, and eventually automated manner.

Distribution Options

  1. Git Repo
  2. Downloader script
  3. Downloader script + FFMPEG to get desired formats
  4. Downloadable archive from Jellyfin Web Server

Supported Test Cases

  1. Add/Browse/Scan Library
  2. Play Media
  3. Subtitle Support
  4. Library Permissions
  5. DLNA Media Server

Sources

  1. GNOME Sample Library Github
    Audio, video, images, multiple formats/quality
  2. jell.yfish.us Test Media jell.yfish.us
    H.264 and H.265/HEVC encoded .mkv video clips that can be used for testing the network streaming and playback performance of media streamers & HTPCs
  3. Internet Archive Feature Films Internet Archive
  4. Blender Open Projects Blender
  5. Public Domain Movies Link
  6. FFmpeg Samples FFmpeg
  7. NASA Downloadable Videos NASA

Discussion on Trick Play / Scrubbing Preview Images

Hi, I wanted to consolidate some of the discussion from this thread from jellyfin-roku as well as this thread from my own plugin repository. I would love to be able to contribute to jellyfin by working on an official trick play functionality, but obviously that requires work on every different client to accomplish, so this is mainly about trying to find a format that can work for all platform developers or at least seeing what platforms would be the easiest to compromise on. From the research I've done:

Formats:

BIF files
A standard originally made by Roku -- essentially just a stream of jpgs

Pros:

  • Easily created/decoded without need for third-party tools (besides already bundled ffmpeg)
  • Relatively easy to create client code to decode and use stream of jpgs
  • Used by Netflix, Disney+, Plex among others
  • Single network request to retrieve trick play data for an entire stream
  • Easily stored and moved

Cons:

  • Only natively supported by Roku, needs specific implementation on Swiftin (or any other native players in the future)

WebVTT
Standard HTML web element (I think)

Pros:

Cons:

  • Only HTML standard? May require additional implementation for native players like Roku, Swiftin
  • Grid of images may make that implementation less simple

HLS
Standard made by Apple for video streaming.

Pros:

  • Natively supported by Roku and tvOS

Cons:

  • Different* implementations of trick play for both Roku and tvOS
  • HLS.js doesn't support any trick play functionality so would also require custom impl

Clients:

tvOS/Swiftin
From what I can find on tvOS, it only natively supports using the HLS tag #EXT-X-I-FRAMES-ONLY which is an additional playlist with segments of individual frames that can be used for scrubbing. The only example I could find of this is here, where each individual preview image is its own .ts transport stream. I'll admit that all of HLS is a bit confusing to me, but if each frame would need to be its own transport stream I see that being a potentially big hassle to implement for static content and for clients that don't natively support scrubbing with #EXT-X-I-FRAMES-ONLY.

Can custom UI elements be used instead for scrubbing to support more formats?

Roku
Natively supports BIF. On their page for "trick mode" it also says SceneGraph (?) natively supports HLS. However, Roku claims on this page that Apple's approach can be less than ideal at times: "The format currently specified by HLS is a coded video I-frame. This approach is efficient because it references frame data directly from the video stream and has the added benefit of supporting digital rights management. However, additional video decoding resources are required to process these I-frames for display, which can be problematic in some cases. To make these images more accessible on a wider range of client devices, Roku supports a second playlist format, which it developed in collaboration with Disney and WarnerMedia". As such, they also support #EXT-X-TILES which are individual jpeg images that are grids containing multiple frames to be used for scrubbing. Theoretically, this means it could be interchangeably used with the images used by WebVTT.

Can custom UI elements be used instead for scrubbing to support more formats?

Web (also currently desktop + mobile)
Easiest to work with, and already has page elements for trick play images. Currently, I've already made support for BIFs but I could see WebVTT working. HLS.js (which I believe jellyfin-web uses) does not support #EXT-X-I-FRAMES-ONLY, and naturally only Roku supports #EXT-X-TILES. I'm really not sure how a custom implementation using #EXT-X-I-FRAMES-ONLY would be accomplished on the web client or on the server side as far as extracting frames goes.

Improve project structure documentation

We should improve the documentation around the structure of the project. Roles and responsibilities should be defined. Possibly including an org chart should be made of how the teams and committees interact with individual sub-projects.

Chromecast Selector

Currently the Chromecast selector is selectable via User Settings > Playback. This has benefits and disadvantages.

Advantages:
It is easy to do testing on a client without impacting the entire server.
Disadvantages:
On every client, you have to remember which version you have selected.
Any user, even inexperienced users may select unstable which may break any and all playback.
You can't prevent users from using unstable if you dont wish them to.

I am making a PR to add a personal Chromecast client

https://github.com/Artiume/jellyfin-web/pull/19

This will be addable via Dashboard > Playback > Streaming

I am tempted to move the chromecast selector to this page as well. It will make it so the admin has full control of which version of chromecast is used. The main disadvantage is that if you decide to test a non-stable client, this will impact the entire userbase.

Provide an API endpoint to submit offline listens

At the moment, the playback session API doesn't allow you to submit sessions from the past, so playback reporting plugins like the ListenBrainz and Last.fm plugin have no (proper) way to record such listens.1

A long time suggestion has been to add a timestamp to the ReportPlaybackStopped API
But because this would require a separate request for every recorded offline listen, I don't think this would be a good solution.
Instead, clients should be able to submit a list of listens once they are online again, which could then be submitted to the activity log and be broadcast to playback reporting plugins so that they could pick them up and submit them to an external service.

By making this an official API, behavior across various plugins could be streamlined and clients would only need to use the Jellyfin API and not need to bother with external services or third-party APIs.
Moreover, an official API should hopefully increase adoption among third-party music playback clients.

I've discussed this with the ListenBrainz plugin developer already and posted some further thoughts in lyarenei/jellyfin-plugin-listenbrainz#51.

There's also a draft for the API design in that ticket. I'd love to discuss the API proposition here further, and afterward work on getting this into the server, if accepted.

[1] The ListenBrainz plugin offers an alternative mode that does actually allow to retroactively submit listens, however, it comes with its own share of disadvantages as outlined in the docs above, and also requires one request per reported offline playback.

Cast receiver configuration

To ease cast client development and make it easier to use third-party/self hosted implementations I propose some changes to how we deal with the cast receiver id in the server/web. The main changes of this proposal are:

  • Configure the available cast receivers
    • Mainly making it possible to host your own without modifying jellyfin-web (or the native clients that implement casting).
  • Remove the hard coded receiver ids from the frontend

I'm searching for someone to tackle the server part of this proposal. I can do the web part myself (although if someone from the web team wants to do that, please do!).

Jellyfin server changes

  • Add "CastReceiverApplications" to system.xml

    • Will have a name & id for the receivers
    • Default to two entries: Stable (F007D354) and Unstable (6F511C87) (our current application ids)
  • Add "CastReceiverApplications" to /System/Info endpoint
    Sample JSON:

    {
      "CastReceiverApplications": [
      	{
      		"id": "F007D354",
      		"name": "Stable"
      	}
      ]
    }

    Clients should use the user preferred cast client or they must use the first returned application.

  • Add "CastReceiver" to UserConfiguration

    • The value is the id of the cast receiver
    • Must be one of the entries in system.xml when the value is updated (doesn't need to be validated on GET)
    • Defaults to first entry in CastReceiverApplications
  • Migrate the existing chromecastVersion property from the usersettings to the new user configuration property

Jellyfin web changes

  • Use the CastReceiverApplications value from the system info in the user playback settings page
  • Use the CastReceiver value from the user config when using cast
  • Remove hardcoded cast client values

This effectively supersedes #7 (which I noticed existed after I made this draft).

Suggestion: settings API to be used by core and plugins

Please close this suggestion if it's not appropriate or if something like that already exists, but from what I have seen so far (still new to jellyfin) at least plugins currently have to provide their own settings HTML page and JS logic, which is IMO a really bad API design choice. Clients are unable to provide any of the settings unless it's the default web UI. And one change in the web UI can break plugin pages from what I gathered.

So my suggestion would be to abstract settings and their handling by using a declarative approach, like a XML, YAML or JSON schema that describes the settings options, their dependencies, visibility conditions (or handlers) etc, the core does read and manage those and the clients are only "dumb" renderers of these settings.
Ever since we switched to this in KODI, managing and extending settings as well as reacting to change events has never been so easy - even I as non C dev managed to add new settings.
The developer who implemented the base settings management handler wrote it in a way that is pretty much agnostic to KODI and can be used by any other project (from what he told back then), so if you wanted you could pick it up and write your own glue code (core interaction, event subscription, ...). If you are interested, this should be the core settings system he wrote back then https://github.com/xbmc/xbmc/tree/master/xbmc/settings/lib

I can provide more info or at least hook you up with people that could provide more info if you are interested. If not, please ignore my suggestion and simply close the ticket again.

Thanks.

Allow for self-nominations for team membership

We should update the project guidelines to allow for contributors to self-nominate to join the Jellyfin team. We will also need some process defined on how the self-nominations will occur (i.e. a GitHub issue, form, or some other method).

Channel Plugin Based on Existing Media Files

Hi,

I want to make a feature and add to this repo, that allows to create local channels out of existing media files.
Take movies for example, movies can be categories into Genres. Each Genre could be a channel.

Primary Motivation is to remove the time taken to select a movie/media file.

Initial Feature List I have in mind -

  1. Create Channels Based on Genre
  2. Randomise movies based on Days, create schedule
  3. Show Schedule.
  4. Show other movie trailers in between movie playback, users shall be given an option to select how many ads. Typically two ads, so movie is splitted in 3 sections. Instead of Trailers, it can be teasers too.
  5. Allow User to skip to next movie in initial 10 min.
  6. 1 Custom Channel, to let user customise the schedule.

For TV I haven't thought too much at the moment. But it could be similar, in future I plan to create different kinds of channels based on common features of Movies or TV Shows.

Project policies and leadership

I would like to bring to attention some point of the policies and processes that I think should be challenged and reworked.

In the interest of clarity, I will go over everything point by point, and provide my arguments, divided into three sections, one for each of the documents.

Since I would like us to be more open in our discussions, I am sharing this publicly in the hopes of bringing good discussion to this.

Jellyfin Social Contract

Source: https://github.com/jellyfin/jellyfin-meta/blob/master/policies-and-procedures/jellyfin-social-contract.md

Jellyfin funds itself exclusively from donations by individual users. It does not and will not accept any sponsorship or other monetary compensation in exchange for features, priority access, support, or any other work by the community.

While this in nice in theory, it is also false, as currently formulated. We do indeed have sponsorships, notably from DigitalOcean and JetBrains.

While these are not in exchange for features, priority support or other development-related areas, they still exist and, currently, would run against this very part of the social contract.

Furthermore, I don't think funding should be part of the social contract itself, but part of a separate funding policy, similar to how Debian handles it.

Finally, limiting donations only to individual users is a bad call. While we should make clear that priority support will not be given as part of Jellyfin itself, we should still allow contributions from organizations and companies wishing to use and contribute to Jellyfin, perhaps through a Platinum/Gold/Silver/Copper sponsorship system, akin to what multiple other open source projects practice.

Jellyfin is built entirely and exclusively by volunteer contributors who donate their free time to the project. Jellyfin will not hire or pay for development or design effort for the project.

This is similarly out of place in a social contract between the project and its community, and potentially limiting to project growth.

While we shouldn't finance development directly as a project, some services might need payment of some sorts, which would run afoul of this clause.

It should, similar to the previous point, live in a separate Funding Policy, if it is to be kept.

Jellyfin builds upon other free software components such as FFmpeg, and will contribute back to that community as much as possible.

This formulation is too vague.

Something like the following would be much better:

We pledge to be good open source citizens and give back to the community
that helps build Jellyfin.
We will communicate things such as bug fixes, improvements and user
requests to the "upstream" authors of works included in Jellyfin.

Jellyfin will not hide problems

I mainly disagree with the disclosure process in this section, but I will talk more about that once we reach the part about the Jellyfin Constitution.

I should say though, that in practice this has not been the case. A lot of communication that should be public is done through private channels instead of public ones, and this, along with other points I shall discuss later, very much makes the project feels like a "boy's club", where only the people who are "in" are privvy to information, while everyone else is left in the dark.

Jellyfin's priority is to our users, which includes most of our contributors as well - we contribute because we use. We will seek to always support our users to the best of our capabilities. We will prioritize free software in all decisions and ensure that users have the same rights. If the needs of our contributors and our users conflict, we will seek consensus and an amicable solution wherever possible.

I don't like the mention of contributors in this section. It should be "users first", contributor or not.

Being a contributor to Jellyfin shouldn't give you more weight than simply using it.

The "we will prioritize free software first in all decisions" makes no sense here. The idea of this section should be to emphasize that we look at the free software community at large, and engage in being good citizens. Instead, this paragraph currently implies that when we're looking at a solution for something, we look at free software first, which shouldn't be the message here.

Jellyfin's contributors will treat each other and our users with respect

Again, this has nothing to do with a social contract between the project and its users, and fits more into a Code of Conduct.

Jellyfin's leadership team will guide the project towards these goals

Again, this has nothing to do here, in my opinion.

everyone keeps the leadership team accountable.

This is also laughable, as I will outline later.

Jellyfin Constitution

Source: https://github.com/jellyfin/jellyfin-meta/blob/master/policies-and-procedures/jellyfin-constitution.md

The Jellyfin Project is organized into a hierarchical structure with the following layers, which shall be defined in more detail below

I think the organization is too rigid and too pyramidal for it to make sense. More detail will follow in further sections, but I also think this should be in a separate document, akin to the Debian Organizational Structure document.

In the list above, a person or body is usually listed before any people or bodies whose decisions they can overrule or who they (help) appoint - but not everyone listed earlier can overrule everyone listed later.

This makes absolutely no sense.

It's essentially saying "Some people can override others' decisions, but not everyone can".

Again, the organization is essentially a pyramid, with higher levels being able to override decisions made by others, without being able to be elected directly by the people they have the power over (more on this soon).

Nothing in this constitution imposes an obligation on anyone to do work for the Project. A person who does not want to do a task which has been delegated or assigned to them does not need to do it. However, they must not actively work against these rules and decisions properly made under them.

Nothing should be delegated or assigned, except to people who volunteered for a position of responsibility over something. But the structure needs to account for that, which it currently doesn't.

A person may hold several posts at one time, and be part of as many teams as desired.

Yes, of course. But there should also be term limits on those positions, to avoid a handful of people holding the power, as is currently the case, with no recourse for change. More on this below.

The Project Leader is responsible for the overall management of the project direction and releases.

This is way too vague and groups the role of Release Management or Packaging Team with the role of project lead, which is idiotic.

There should be a Release Management/Packaging Team which handles releases and packaging, and it shouldn't be tied to the role of project leader. The functions require different skillsets and types of work, as well as responsibilities.

Furthermore, compared to the Debian Constitution, this is too vague as to the exact roles of the Project Leader and is ripe for abuse.

One example would be Section 5.1.9 of the Debian Constitution, which is completely absent here. I cite: "The Project Leader should not use the Leadership position to promote their own personal views".

In fact, our contribution explicitely states the following: "The Project Leader is responsible for the overall management of the project direction". Taken as-is, this means essentially that the project is dependent on the whims of its current Project Leader, which may veto or push for any one thing they want, which should be impossible for a properly structured project.

While the Project Leader should set a global direction for the project, they should, like outlined in the Debian Constitution, do so by talking with team members and only intervene to help in resolving urgent matters, matters with no current delegate or appoint delegates.

The Project Leader is the final arbiter in any disputes or decisions raised from lower teams and persons where such a decision cannot be reached by more collaborative means within the teams themselves.

The phrasing of this section once again emphasizes how the Project Leader has the ultimate authority, which they shouldn't have.

Per the Debian Constitution, again: "The Project Leader should attempt to participate in discussions amongst the Developers in a helpful way which seeks to bring the discussion to bear on the key issues at hand".

The role shouldn't be about making decisions, but about making sure things run smoothly.

The Project Leader shall also function as Release Manager for the core server, handling the coordination and creation of new releases of the Jellyfin server software. Creation of releases for clients or sub-components is delegated to their respective Function Teams.

This goes with the point made above about merging Project Leader and Release Management, two very different functions.

Why would the Project Leader, whose role should be to ensure the smooth running of day to day operations and team collaboration, also imply the need to be able to:

  • Package software
  • Cut releases
  • Act as a sysadmin by managing server-side scripts to pull and organize releases

These are different skills and completely unrelated to the role of a Project Manager.

The Project Leader must always be a member of both the Leadership Team and the Financial Committee.

This seems ripe for abuse, and gives even more power to what should essentially mainly be a guiding role.

While expenses should first go through the Project Leader for validation, treasurers should be the only ones with direct money access.

The Project Leader shall serve indefinitely at their discretion, but may resign at any time.

This, in my opinion, is unacceptable.

This makes the project essentially a ************, with no recourse in case of abuse, incompetence, disagreement or other issue.

It goes completely counter to the very notion of free software. The constitution as a whole seems to try to make what is essentially a ************ by a minority over the project, as a democracy.

Every role should, in my opinion, have term limits, to ensure the role (and the project as a whole) doesn't get stagnant and rots from the inside.

Since the Jellyfin Constitution is based upon the Debian Constitution, I would propose a term duration of one year for the Project Leader, with voting from all Jellyfin members in a publicly held election.

Upon resignation or in-disposal of the Project Leader, one or more candidates for the position shall be proposed by the Leadership Team.

This promotes the incestuous nature of the Leadership Team, by ensuring that only the Leadership Team can appoint new members to the Project Leader role, while also being the only power to be able to appoint members to itself.

In practice, this makes it so only a select number of members hold any real power over the project's direction and future, and is set up explicitely to make it stay that way.

A system similar to Debian's is much more democratic and difficult to abuse. I quote: "For the first week any Developer may nominate themselves as a candidate Project Leader, and summarize their plans for their term".

The method of election shall be ranked voting instant runoff until one candidate has secured an absolute majority of the vote. In the event that only a single candidate is proposed, and this candidate does not gain a majority of votes among the Contributor Team, the outgoing Project Leader shall cast a deciding vote to confirm or deny the candidate outright. If the outgoing Project Leader does not confirm the candidate, the process shall begin again and the previous candidate is ineligible for further consideration.

This method of voting is, again, ripe for abuse.

A better suited method, explictly intended to avoid the outgoing Project Leader having to confirm anything, would be the Condorcet method. This is already used by Debian, the Wikimedia Foundation, the Gentoo Foundation and the Kubernetes community.

De facto, an outgoing Project Leader should not have any say over who their successor is, although they should still have a vote in the election, as with every other member.

The Leadership Team is responsible for the day-to-day operations of the project and the handling of technical and managerial decisions for the project.

I am not sure there should be a leadership team at all.

They do essentially the role of the current Project Leader, but hold private discussions and hold way too much power.

The Leadership Team is the only group with "Merge" permissions for the core server repositories, and are responsible for the merging of reviewed and approved Pull Requests into those repositories.

Then this should be the "Server Team", not the "Leadership Team". If they handle the direction of a component of the project, they should be that component's team, not one that holds infinite power over the entire project.

The initial Leadership Team was appointed by the first Project Leader during the creation of the project and has and shall continue to grow.

Again, there should be term limits for this, as currently the team elects itself and regulates itself, which is ripe for abuse and promotes an incestuous relationship at the top levels of the project.

The Leadership Team should, but is not required to, include an odd number of active members to ensure majority decisions can be decided effectively.

This is not needed at all, since teams should be able to self regulate (as the Leadership Team should not exist).

Individual component's teams should work on a 2/3rd of votes decision system, to ensure that no matter the amount of people in the team, a consensus can be reached.

New members can be proposed to the Leadership Team when required by the Project Leader

This once again promotes a "boy's club" approach to leadership, and encourages incestuous relationships, where developers have no way of getting any say in things unless they get in the good graces of the Leadership Team and the Project Leader.

Members of the Leadership Team shall be removed from their position after 1 year of inactivity with the project, subject to discussion by the remaining Leadership Team members.

This has not been applied in practice and, even if it was, term limits should be in place for any position affording authority.

The term "inactivity" is also very vague. What constitutes inactivity in the eyes of this sentence?

Some members of the Leadership Team have been essentially invisible from the project at large, either not contributing at all, being MIA or only hanging out in chatroom, yet they are apparently not considered "inactive".

The Financial Committee is a sub-group of the Leadership Team who is in charge of allocating funds from the OpenCollective donation pool.

This, once again, places all the power in the hands of the same few (unelected and unremovable) people.

The Financial Committee shall always include exactly 3 members to ensure transparency in all funds allocations.

Having three members does not provide any transparency by itself.

New members shall be proposed by the existing Financial Committee should the need arise, by direct nomination by the departing member. The new member must be confirmed unanimously by the remaining members.

Same as a lot of other points above, this essentially makes sure the power stays in the hands of a select few, who are unelected and unremovable.

New Subproject Leaders shall be selected by the Project Leader, in consultation with the Leadership Team and existing sub-project contributors, as required.

Projects should elect their own team's chair, as they are the ones closest to the daily work and capabilities of everyone involved in it.

As with other leadership roles, there should be regular elections for this.

Technical Committees exist to facilitate day-to-day decisions on technical matters within the Jellyfin Project, and are empowered to make technical decisions related to their area of expertise.

This should not be the purpose of a Technical Commitee.

They should essentially be there to make decisions that cross multiple projects' jurisdictions and otherwise act in an advisory role. They may override some technical decisions from developers at times, but mainly in cases of issue resolutions.

Membership should not be based upon being in the Leadership Team (which, again, shouldn't exist at all), but appointments should be made by the (elected) Project Leader and the rest of the technical commitee.

The Project Leader should only get a vote in a tie-breaking situation.

Technical Committees shall consist of exactly 3 members

Why 3? Again, section 6.3 of the Debian Constitution makes a lot more sense than this, and has better processes.

Term limits should also apply, to avoid a stagnant set of members.

Technical Committees shall make all decisions by consensus

This limits decisions a lot. Having a 3:1 majority, with a strict minimum of 4 members would allow a lot more leeway for decision-making.

The exact list and nature of the Technical Committees shall be subject to decision by the Project Leader and Leadership Team as required, and Technical Committees shall be created or dissolved as needed by the project as a whole.

The Technical Committee should be a permanent fixture, but should also be able to appoint itself in cases where member counts dip too low. Again, Debian has good policies for this, why change them to worse, more authoritarian ones?

New team member nomination process

Anyone who is currently on the Jellyfin team (defined as a member of #jellyfin-support-team and/or the GitHub organization) may nominate a community member for inclusion in the team.

This makes the process incredibly limiting, and reinforces that "Boy's Club" mentality.

Similar to Debian, potential new members should be able to nominate themselves by providing a letter of intent, then agree to the policy documents.

Eventual advocates should manifest themselves, then the application should be reviewed before being submitted to a public vote of a fixed duration.

If either a majority of votes are positive, or there is a lack of opposing votes after the end of the time period, the nominee should become a part of the organization.

With such a process, the rest of the document is de-facto made irrelevant.

Such a process ensures that "getting in" is doable for everyone and the organization can grow based on contributor interest instead of "being noticed", making us more open as an organization.


I think the current policy documents emphasize a lot of the issues we have as a project, some of which I have already brought up before.

We present ourselves as open and "do-ocratic" (which, per the definition, implies a democracy), but in practice the policies of the project promote a closed loop of leadership, and stiffle potential progress and project growth.

While I am aware that I am directly criticizing a lot of things and indirectly calling out people here, my intention with this is merely to highlight what I feel are deep organizational issues within the project, which would merit being talkked about and fixed.

We should strive to be more open and democratic, or we should remove "Jellyfin is a community [...] effort" and the "we are free software" parts of the Social Contract, because our current policies run counter to these two points.

Sources for Axios Client

Currently, we build and publish the Axios client manually. Build scripts, documentation for building and sources are nowhere to be seen, we don't provide anything else but the npm package.

Specially needed for jellyfin-chromecast implementation

Moving forward for Standardized Git descriptions commits subject and descriptions when merging PR's with Master.

At times, looking at the git history can be a bit hard on the eyes as there seems to be no consistency with git commit subject lines and description.

Currently, you need to click on the pr id just to figure out what the commit is about.

Screenshot_20231007_122252_GitHub.jpg

This is only a suggestion with examples.
Why not put the pr# in the commit description and then the subjectline be in a formate of add/feat/fix/revert/chore, with area identifer in the title and brief summary less than 50 characters.

Then, for the body message, we list in detail the purpose of the commit, followed by pr# that was merged.

Start identifier:
Add: additional implementation of existing features
Feat: Adding new features not currently implemented
Fix: Fixing an issue or "bug" either reported or not
Revert: Reverting either a commit or partial commit
Chore: dependency update or white space/code style clean up, updating/simplifying methods/code blocks etc..

Area identifiers to follow:
Core: code base itself
Doc: documentation
Dep: dependiences
Misc: Miscellaneous

Summary:
Self explainatory, 50 chars or less

An example would be when we merge a pr:

SUBJECT LINE:
Fix (core): black screen issue

BODY DESCRIPTION:
fixed an issue with black screens yadda yadda.
Pr#12345

Something like this, moving on in the future, would make the githistory more readable and easily searchable with various git apps such as tortoisegit and others. Would possibly help in also researching past commits as well when attempting to identify any commit/issues dealing with anything ongoing.

Again, this is only a suggestion with examples. Really, it will be up to the project maintainers and admins to decide on what is appropriate.

Edited: typos

10.7 Known Issues

Migrated from @thornbill's gist

10.7 Hit List

Bugs

UI Issues

  • Improve item detail mobile layout (backdrops for People, Albums, etc.) jellyfin/jellyfin-web#2246
  • Quick Connect polish jellyfin/jellyfin-web#2155
  • Button sizes are very inconsistent (very noticeable in admin dashboard) (partially fixed in jellyfin/jellyfin-web#2128)
  • blurhash bleed through around images
  • Video OSD large padding on bottom on mobile
  • Noto Sans should use locally installed version when available
  • Poster position off sometimes (should be sticky?)
  • Plugin page lacks padding at top and icons are not centered in cards

Related to Networking changes

  • Enabling IPv6 wildcard bind (to [::]) crashes Kestrel on startup; binding to a specific v6 addr is fine.
  • Disabling Autodiscovery does not disable listening on the autodiscovery port.
  • Client IP address is wrong by default when behind a proxy jellyfin/jellyfin#4670

DLNA is not IPv6 capable in 10.7 (is part of the next set of PR's), so enabling IPv6 may stop it from working. Recommended to leave IPv6 disabled if using DLNA.

Python land

MPV Shim Issues

  • Cannot cast to MPV Shim or to another copy of the web player.

Players aren't listed. Capabilities/Full post succeeded. Docker unstable as of 2020-11-26 15:15 EDT.

  • Initially I had problems with navigation not working, instead it just always seeks to beginning. I can't test at all now due to first issue.
  • SyncPlay needs to be fixed/re-implemented in MPV Shim.
  • jellyfin/jellyfin#3931
  • jellyfin/jellyfin#3855

If there is progress on any of these, let me know via @ here or in Matrix. I would love to get everything working before release.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.