GithubHelp home page GithubHelp logo

jesseward / discogstagger Goto Github PK

View Code? Open in Web Editor NEW
70.0 9.0 13.0 191 KB

Console based audio-file metadata tagger that uses the Discogs.com API v2 (JSON based). Relies on the Mutagen and discogs-client libraries. Currently supports FLAC and MP3 file types.

License: MIT License

Python 100.00%
mp3 discogs metadata audio mutagen python discogs-client audio-tag flac

discogstagger's Introduction

STATUS

Note that this utility is no longer maintained.

discogstagger

Build Status

What is it

discogstagger is a console based audio meta-data tagger for FLAC, Ogg and MP3 audio files. Album, artist and track data profile is retrieved via the discogs.com API and then saved to the related metadata fields in the audio container.

To tag an album, provide the script with a target directory name (-s), that contains an album consisting of supported media files as well as the discogs.com release-id (-r). discogstagger calls out to the discogs.com API and updates the audio meta-data accordingly.

If no release-id is given the application checks if a file "id.txt" exists (the name of this file can be configured in the configuration) and if this file contains a specific property (id_tag). If both is true the release-id from this file is used. This is useful for batch processing.

During the process, all album images (if present) are retrieved from the API. As well, a play-list (.m3u) and an information file (.nfo) are generated per each release.

Optionally discogstagger will embed the found album art into the file meta data

Requirements

  • Mutagen
  • discogs-client
  • requests
  • Mediafile
  • OAuth

I am also packaging/reusing the MediaFile library from the "beets" project. This will be packaged with discogs tagger until MediaFile is split out to its own package.

Installation

Fetch the repo from github

git clone https://github.com/jesseward/discogstagger.git

Create a virtual environment for your installations

python3 -m venv ~/.virtualenvs/discogstagger
source ~/.virtualenvs/discogstagger/bin/activate

Run the setuptools installation.

python setup.py install

Optionally you can install the developer requirements, if you plan on running the test suite or making changes to the tool

pip install -r dev_requirements.txt

Configuration

DiscogsTagger searches for the configuration file at the default location of ~/.config/discogstagger/discogs_tagger.conf, at run-time. Or you're able to specify the config location with the '-c' switch.

The configuration file must be present to execute the script. The default settings (as shipped), should work without any modifications.

Note that you may wish to modify the following default configuration options. The defaults are shipped as such in attempt to be as non destructive as possible

# True/False : leaves a copy of the original audio files on disk, untouched after 
keep_original=True
# Embed cover art. Include album art from discogs.com in the metadata tags
embed_coverart=False

To specify genre in your tags, review the use_style option. With use_style set to True, you're instructing discogstagger to pull the "Style" field. The style field is typically more genre specific than the discogs "Genre" field. In the example below (40522) with use_style=True, the genre field is tagged as "House".

Use Discogs "style" elements instead of the genre as the genre Meta-Tag in files (True)
Example http://www.discogs.com/Blunted-Dummies-House-For-All/release/40522
Style = House
Genre = Electronic
use_style=True

Furthermore you can use lowercase directory and filenames using the following configuration:

# Use lowercase filenames
use_lower_filenames=True

For batch-mode tagging, it is not necessary anymore to provide the release-id via the '-r' parameter on the commandline. The same is possible by using a file (by default: id.txt) with the key/value pair 'discogs_id'. This can be configured in the configuration via the following parameters as well:

[batch]
# if no release id is given, the application checks if a file with the
# name id_file (in this case id.txt) is in the source directory,
# if it is there the id_tag is checked (discogs_id) and assigned to the
# release id
id_file=id.txt
id_tag=discogs_id

Please note, that right now there is no error-handling, if there is no '-r' parameter and no id.txt file. The program will then just exit with an error message.

The command line takes the following parameters:

$ discogs-tagger --help
Usage: discogs-tagger [OPTIONS]

Options:
  -c, --conf TEXT         The discogstagger configuration file.
  -d, --destination TEXT  The (base) directory to copy the tagged files to
  -r, --releaseid TEXT    The discogs.com release id of the target album
  -s, --source PATH       The directory that you wish to tag
  --help                  Show this message and exit.

Examples

The following tags the directory "Pepe_Bradock-Deep_Burnt" with discogs release id '204' (http://www.discogs.com/release/204)

$ discogs-tagger -s Pepe_Bradock-Deep_Burnt -r 204
2017-07-17 04:36:30,686 discogstagger.main INFO     Attempting to tag files from target destination=Pepe_Bradock-Deep_Burnt
2017-07-17 04:36:31,044 discogstagger.discogsalbum INFO     Fetching discogs release. artist=Pépé Bradock & The Grand Brûlé's Choir, title=Burning, id=204
2017-07-17 04:36:31,047 discogstagger.main INFO     Tagging album 'Pépé Bradock & The Grand Brûlé's Choir - Burning'
2017-07-17 04:36:31,047 discogstagger.main INFO     Creating destination directory 'Pepe_Bradock_and_The_Grand_Brules_Choir-Burning-(KIF_S_A_08)-1999-jW'
2017-07-17 04:36:31,048 discogstagger.main INFO     Downloading and storing images
2017-07-17 04:36:33,966 discogstagger.main INFO     Writing file Pepe_Bradock_and_The_Grand_Brules_Choir-Burning-(KIF_S_A_08)-1999-jW/01-Pepe_Bradock_and_The_Grand_Brules_Choir-Burning_Hot.mp3
2017-07-17 04:36:34,011 discogstagger.main INFO     Writing file Pepe_Bradock_and_The_Grand_Brules_Choir-Burning-(KIF_S_A_08)-1999-jW/02-Pepe_Bradock_and_The_Grand_Brules_Choir-The_Right_Way.mp3
2017-07-17 04:36:34,032 discogstagger.main INFO     Writing file Pepe_Bradock_and_The_Grand_Brules_Choir-Burning-(KIF_S_A_08)-1999-jW/03-Pepe_Bradock_and_The_Grand_Brules_Choir-Deep_Burnt.mp3
2017-07-17 04:36:34,054 discogstagger.main INFO     Generating .nfo file
2017-07-17 04:36:34,056 discogstagger.main INFO     Generating .m3u file
2017-07-17 04:36:34,056 discogstagger.main INFO     Tagging complete.

discogstagger's People

Contributors

jesseward avatar triplem avatar vreon avatar wesrog avatar

Stargazers

 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  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  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

discogstagger's Issues

copy_other_files not working for multi-disc

Copied from issue #36

For the above release I had a folder with 5 sub-folders in it. I found that copy_other_files=True doesn't work for all the 5 folders but only the first one (I also use #discs=-CD to collect all output tracks in one- folder).

discogs tracklist is zero

I'm bunching up 2 issues I encountered into this post and two query/feature request

  1. I ran into a track number matching issue - releases like 998336 for example are reported back as having zero tracks and hence not matched to the total number of tracks in the folder (24 in this case). It seems any track on discog with the return carriage sign is not recognised - I tried another album which had 2 tracks out of 18 marked the same and discotagger reported back 16 tracks in the album instead of 18.

  2. I coulnd get the batch feature to work. No matter how I named the text file inside the folder (id or id.txt or id_file) and the release number inside it (id_tag=998336 or 998336 or discog_id=998336) it always asked for the -r parameter. I have the latest version installed.

  3. query/feture request

  • is there a way to prosess more than one folder at once?
  • would it be possible to have an automatic work-around for spaces in the folder names? I found that simply dropping the path to the folder into the terminal doesn't work - and I need to put \ in front of each space which is not ideal.

thanks a lot

CD No matching in track naming not working

I use song=%DISCNO%-%TRACKNO% %TITLE% in the config file and found that it works half-way.
It works for one disc releases, it did work for one release with two discs (sorry, can't remember which one exactly).
However, it didn't work for multi-album releases like 8044338. The disc No info is there but I ended up with tracks named 01-01 to 01-forty something instead of 01-01 to 01-10; 02-01 to 02-12 etc. (actually it's 1-01 and not 01-01. Leading zero (as in 01, 02 etc) for disc numbers will be much preferred.)

For the above release I had a folder with 5 sub-folders in it. I found that copy_other_files=True doesn't work for all the 5 folders but only the first one (I also use #discs=-CD to collect all output tracks in one- folder). Moving to Issue #37

Thanks a lot

Images won't download

Hey. i'm getting this error while fetching infos from discogs.

ERROR:discogstagger.taggerutils:Unable to download image '', skipping. Error: Unsupported URL ().

Can't authenticate (Status 301)

Dear jesseward,

thanks for this great script!

However, I can't get the image download to work and will allways receive the status response 301. The discogs API doc won't tell me what that means. Please see traceback for details.

Best regards,

Tim

Traceback (most recent call last):
  File "/usr/local/bin/discogs_tagger.py", line 204, in <module>
    get_images(release.album.images, dest_dir_name, images_format, first_image_name)
  File "/usr/local/lib/python2.7/site-packages/discogstagger/taggerutils.py", line 316, in get_images
    discogs_auth = DiscogsAuth()
  File "/usr/local/lib/python2.7/site-packages/discogstagger/discogsauth.py", line 30, in __init__
    self._get_request_token()
  File "/usr/local/lib/python2.7/site-packages/discogstagger/discogsauth.py", line 43, in _get_request_token
    raise Exception('Invalid response {0}.'.format(resp['status']))
Exception: Invalid response 301.

Truncate Excessively Long Filenames

I'm trying to tag an album with excessively long track names, which is a problem for the resulting filenames:

OSError: [Errno 63] File name too long: 'Red Krayola - Fingerpainting (1999) JV/05 The Greed Of A Clarinet That Is Puffy From Crying Gets Tossed In Butter And Spread By Notes  This Process Depresses The Entire Orchestra So Much That It Only Plays Behind A Golden Partition  The Partition Is Decorated With Semi-Precious Attractive Diamonds.flac'

I'm leaving the issue here in case you ever decide to come back and polish / test various edge cases. :-)

Track matching issue . Support for sub_tracks

Creating from issue #33

I ran into a track number matching issue - releases like 998336 for example are reported back as having zero tracks and hence not matched to the total number of tracks in the folder (24 in this case). It seems any track on discog with the return carriage sign is not recognised - I tried another album which had 2 tracks out of 18 marked the same and discotagger reported back 16 tracks in the album instead of 18.

example JSON
https://www.discogs.com/release/998336
https://api.discogs.com/releases/998336

  "tracklist": [
    {
      "duration": "",
      "position": "",
      "type_": "index",
      "title": "Pictures At An Exhibition",
      "sub_tracks": [
        {
          "duration": "1:42",
          "position": "1",
          "type_": "track",
          "title": "Promenade"
        },
        {
          "duration": "2:58",
          "position": "2",
          "type_": "track",
          "title": "I. Gnomus"
        },
        {
          "duration": "1:02",
          "position": "3",
          "type_": "track",
          "title": "Promenade"
        },
        {
          "duration": "5:29",
          "position": "4",
          "type_": "track",
          "title": "II. Il Vecchio Castello"
        },
        {
          "duration": "0:35",
          "position": "5",
          "type_": "track",
          "title": "Promenade"
        },
        {
          "duration": "1:06",
          "position": "6",
          "type_": "track",
          "title": "III. Les Tuileries"
        },
        {
          "duration": "4:19",
          "position": "7",
          "type_": "track",
          "title": "IV. Byd&#322;o"
        },
        {
          "duration": "1:02",
          "position": "8",
          "type_": "track",
          "title": "Promenade"
        },
        {
          "duration": "1:46",
          "position": "9",
          "type_": "track",
          "title": "V. Ballet Des Poussins Dan Leur Coque"
        },
        {
          "duration": "2:45",
          "position": "10",
          "type_": "track",
          "title": "VI. Samuel Goldenberg Und Schmuyle"
        },
        {
          "duration": "1:43",
          "position": "11",
          "type_": "track",
          "title": "Promenade"
        },
        {
          "duration": "1:22",
          "position": "12",
          "type_": "track",
          "title": "VII. Limoges - Le Marché"
        },
        {
          "duration": "2:18",
          "position": "13",
          "type_": "track",
          "title": "VIII. Catacombae: Sepulcrum Romanum"
        },
        {
          "duration": "3:54",
          "position": "14",
          "type_": "track",
          "title": "Con Mortuis In Lingua Mortua"
        },
        {
          "duration": "4:10",
          "position": "15",
          "type_": "track",
          "title": "IX. La Cabane Sur Des Pattes De Poule"
        },
        {
          "duration": "6:07",
          "position": "16",
          "type_": "track",
          "title": "X. La Porte Des Bohatyrs De Kiev (La Grande Porte De Kiev)"
        }
      ]
    },
    {
      "duration": "",
      "position": "",
      "type_": "index",
      "title": "Valses Nobles Et Sentimentales",
      "sub_tracks": [
        {
          "duration": "1:39",
          "position": "17",
          "type_": "track",
          "title": "I. Modéré - Très Franc"
        },
        {
          "duration": "3:00",
          "position": "18",
          "type_": "track",
          "title": "II. Assez Lent, Avec Une Expression Intense"
        },
        {
          "duration": "2:45",
          "position": "19",
          "type_": "track",
          "title": "III. Modéré"
        },
        {
          "duration": "1:33",
          "position": "20",
          "type_": "track",
          "title": "IV. Assez Animé"
        },
        {
          "duration": "2:03",
          "position": "21",
          "type_": "track",
          "title": "V. Presque Lent, Dans Un Sentiment Intime"
        },
        {
          "duration": "0:30",
          "position": "22",
          "type_": "track",
          "title": "VI. Vif"
        },
        {
          "duration": "3:24",
          "position": "23",
          "type_": "track",
          "title": "VII. Moins Vif"
        },
        {
          "duration": "4:36",
          "position": "24",
          "type_": "track",
          "title": "VIII. Epilogue: Lent"
        }
      ]
    }
  ],

Set Tags from specific file (id.txt) manually

Right now we are just using the discogs_id from the id.txt and set this in the Tags of the audio files. Allow for other tags as well.

In a first step I am thinking about the "encoder" field, but similar all other fields (even those fetched from discogs), could be set in the id.txt.

windows install

Just in case someone wish to install on w10, I had to change this :
os.path.expanduser('~{0}/.config/{1}/'.format(user, NAME)),
to this
os.path.expanduser('~/.config/{1}'.format(user, #NAME)),
in setup.py to make installation possible
#24

As well, had to change this :
self.token_file = os.path.expanduser('~{0}/.config/discogstagger/token'.format(user))
to this :
self.token_file = os.path.expanduser('~/.config/discogstagger/token'.format(user))
in discogswrapper.py to make the tagging command to work

Copy additional files from source folder to destination

Some additional files are in my source folders (e.g logs, additional informations), these should be copied to the destination folder as well

I can think of a couple of problems here:

  • the file does exist already in the destination folder and should not be over written (e.g. m3u file)
  • the file is not up to date anymore (e.g. Cue file, because of renamed files)

Add support for multi disc releases

Currently all tracks of one release should be in on directory, on multi disc releases it is quite common to habe each disc in a separate folder. This should be supported as well.

AttributeError: 'NoneType' object has no attribute 'group'

Trying to tag 1704873 - https://www.discogs.com/Various-Pong/release/1704873 - https://archive.org/details/Va-Pong

Full output:

$ discogs_tagger.py -s Va-Pong -r 1704873 -d Va-Pong_tagged
INFO:__main__:destdir set to Va-Pong_tagged
INFO:__main__:Using destination directory: Va-Pong_tagged
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): api.discogs.com
INFO:discogstagger.discogsalbum:Fetching Various - Pong (1704873)
Traceback (most recent call last):
  File "/usr/local/bin/discogs_tagger.py", line 166, in <module>
    split_artists, split_genres_and_styles, copy_other_files, char_exceptions)
  File "/usr/local/lib/python2.7/dist-packages/discogstagger/taggerutils.py", line 64, in __init__
    self.tag_map = self._get_tag_map()
  File "/usr/local/lib/python2.7/dist-packages/discogstagger/taggerutils.py", line 178, in _get_tag_map
    track.tracknumber, position, fileext)
  File "/usr/local/lib/python2.7/dist-packages/discogstagger/taggerutils.py", line 105, in _value_from_tag
    format = self._value_from_tag_format(format, trackno, position, filetype)
  File "/usr/local/lib/python2.7/dist-packages/discogstagger/taggerutils.py", line 79, in _value_from_tag_format
    "%YEAR%": self.album.year,
  File "/usr/local/lib/python2.7/dist-packages/discogstagger/discogsalbum.py", line 130, in year
    return good_year.match(str(self.release.data["year"])).group(0)
AttributeError: 'NoneType' object has no attribute 'group'

TypeError: get() takes exactly 1 argument (3 given)

Hi,

First of all, I'm not a power user of python. I try to run your script with python 2.7.2, mutagen 1.20 and requests 0.10.1 and I have this error :

Traceback (most recent call last):
File "./discogs_tagger.py", line 488, in
logging.info("Tagging album '%s - %s'" % (release.artist, release.title))
File "./discogs_tagger.py", line 140, in artist
artist = self.release.artists[0]
File "/home/cmaussan/code/ext/discogstagger/discogs_client.py", line 141, in artists
self._artists = [Artist(a['name']) for a in self.data.get('artists', [])]
File "/home/cmaussan/code/ext/discogstagger/discogs_client.py", line 52, in data
if self._response.content and self._response.status_code == 200:
File "/home/cmaussan/code/ext/discogstagger/discogs_client.py", line 38, in _response
self._cached_response = requests.get(self._uri, self._params, self._headers)
TypeError: get() takes exactly 1 argument (3 given)

Do you know how to solve this ?

Thanx,

Camille.

Not clear how to work multiple CD albums

I read the user guide here, and I went through the code. I see that in the config file there are options about multi-discs issues. However, is not really clear how to tag them.

What's the typical strategy? I tried to put the files into two directories with various names: I tried CD01 and CD02, also 1-CD and 2-CD, etc. But none of this worked.

How to do it?

Ability to write both style and genre

Hi, I'm wanting a script that can rewrite my entire collection for me. My preferred method would be to delete existing tags and write genre and style independently to separate tags, ie. genre tag and style tag. Is this possible?

Also, on discog I've noticed that sometimes its beneficial to get the genre/style tags from the "All versions" page of an album since its tags are often more complete / reviewed. This would be a nice feature to add I think.

Lastly, I prefer to also destroy any artwork from each track and just store images in the album folder, can discogstagger do this?

Cheers

Embed cover image in tag

At first, your script seems perfect for me! Thanks for releasing it! One thing is missing tho.

I just read through the discogstagger discussion here: http://www.discogs.com/help/forums/topic/251892

The topic is too old to reply, so I ask here:
Can you implement a trigger to embed album art in the media files? Or recommend a script which does?
I have never used python before, so I'm not able to do it.
Here is a discussion about embedding cover artwork in images:
http://stackoverflow.com/questions/7275710/mutagen-how-to-detect-and-embed-album-art-in-mp3-flac-and-mp4

Discogstagger On Windows. Is it possible?

Hello,

Discogstagger is a great tool for anybody loves serious music organization. I am on a dual boot machine windows/linux and i would like it to be accessible from both oses. Is it possible? I really need this Great Tool.

Thanks!

Add check if Discogs release matches local release

Would be great to have the possibility to perform a check if the Discogs release and the local release do match. For example if one track is missing on the local release, all tracks will be written wrong without a check.

Keep spaces in track names?

Is there any way to keep spaces in track names? I removed the default {space}=_ substitution rule in the config, but it seems to remove spaces anyway.

I'd also like the option to avoid generating the nfo file and m3u playlist, but those are easy to manually delete.

Adopt config handling

Some properties (e.g. discogs release id) can already be configured via the "id.txt" file in a directory. Allow for all (or almost all) config parameters to use this functionality, so that different Albums can be generated using different file formats.

Add option to delete comments

A lot of programs use the comment tag to store (unwanted) information. An option to delete them would be nice!

--rmcomments !?

Refactor discogs_tagger.py

This module has slightly outgrown itself. I believe we should do a refactoring, to make future enhancements easier.

There are a couple of opportunities here:
Make the whole config handling easier -> handle this in its own module and use the parameters from an object, this will also make the setting of default values easier, in that those are not set in the taggerutils.py but in the one configure handling module.
Refactor the track-loop, so that this can be adopted easier then right now. Probably we should define an own object "Track"/"TrackContainer" and define certain properties on this one.
Refactor the source directory determination to allow for batch calls (e.g. my source dir is ~/Music and in there are several sub-directories which contain audio files). Up until now the source dir has to contain (except multi-disc releases) audio files.

URL double encoded

Hi Jesse,

I have an other issue with discostagger :/
When I try this command line :

python ~/code/ext/discogstagger/discogs_tagger.py -r 3406100 -s Nordic\ by\ Night

I get this result :

INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): api.discogs.com
DEBUG:requests.packages.urllib3.connectionpool:"GET /release/3406100 HTTP/1.1" 200 2225
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): api.discogs.com
DEBUG:requests.packages.urllib3.connectionpool:"GET /artist/Lindstr%25C3%25B8m HTTP/1.1" 404 75
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): api.discogs.com
DEBUG:requests.packages.urllib3.connectionpool:"GET /artist/Lindstr%25C3%25B8m HTTP/1.1" 404 75
INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): api.discogs.com
DEBUG:requests.packages.urllib3.connectionpool:"GET /artist/Lindstr%25C3%25B8m HTTP/1.1" 404 75
Traceback (most recent call last):
File "/home/cmaussan/code/ext/discogstagger/discogs_tagger.py", line 484, in
logging.info("Tagging album '%s - %s'" % (release.artist, release.title))
File "/home/cmaussan/code/ext/discogstagger/discogs_tagger.py", line 141, in artist
return self.clean_name(artist.data['name'])
File "/home/cmaussan/code/ext/discogstagger/discogs_client.py", line 90, in data
raise HTTPError(status_code)
discogs_client.HTTPError: HTTP status 404: Not Found.

I can see it's because of the double encoding in URL. The GET should be /artist/Lindstr%C3%B8m and it's actually /artist/Lindstr%25C3%25B8m. I tryed to comment the urllib.quote( of line 81 in discogs_client.py but nothing changed :(
Maybe it's in requests.get ...

Do you have any idea ?

Thanks,

Camille.

Make Tags multi-value aware

Right now, we can split multiple values in tags with a configurable value (e.g. ). This makes it possible to split these tags into multi value fields by e.g. puddletag. This should be done directly from discogstagger.

Since we are using mediafile.py from the beets-project this depends on the issue #119 in there repository:

beetbox/beets#119

Batch features no longer working.

Created from issue #33

I coulnd get the batch feature to work. No matter how I named the text file inside the folder (id or id.txt or id_file) and the release number inside it (id_tag=998336 or 998336 or discog_id=998336) it always asked for the -r parameter. I have the latest version installed.

oauth issue

Hello Jesse,

I absolutely love your app (where do I donate?) but I am having an issue using the oauth addition. This is the error I get. Can you please help me? Thanks!

Traceback (most recent call last):
File "/usr/local/bin/discogs_tagger.py", line 204, in
get_images(release.album.images, dest_dir_name, images_format, first_image_name)
File "/Library/Python/2.7/site-packages/discogstagger/taggerutils.py", line 317, in get_images
discogs_auth = DiscogsAuth()
File "/Library/Python/2.7/site-packages/discogstagger/discogsauth.py", line 29, in init
self._get_request_token()
File "/Library/Python/2.7/site-packages/discogstagger/discogsauth.py", line 42, in _get_request_token
raise Exception('Invalid response {0}.'.format(rep['status']))
NameError: global name 'rep' is not defined

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.