Code Monkey home page Code Monkey logo

gabin's Introduction

Gabin

Automate camera switching with OBS, Bitfocus Companion and any audio api.

Screenshot 2023-01-18 at 10 08 19

Download

You can download the latest version of Gabin here.

Features

  • ⚡️ Vue 3, pnpm - born with fastness
  • 🖌️ unocss for ultra-fast tailwind-compatible styling
  • 💬 socketIo for main/renderer communication
  • 🚀 GitHub Actions to build & release app

Usage

Development

pnpm i
pnpm dev

Build

pnpm build

Known issues

  • ASIO is not working with XR32 audio mixer

Documentation

CLI

Gabin can be called in command line with several options :

  • -h, --help : Display this message
  • -d, --debug : Enable debug mode
  • -v, --version : Display version
  • --no-auto-open : Disable auto open in browser

Environment variables

You can add environment variables :

  • GABIN_HOST : Hostname to use (default: localhost)
  • GABIN_HTTP_PORT : Port to use (default: 1510)
  • GABIN_OSC_PORT : Port to use (default: 32123)
  • GABIN_BASE_URL : Base url to use (default: /)
  • GABIN_LOGS_FOLDER : Folder to store logs (default: $appdata/gabin/gabin.log)
  • GABIN_CONFIG_FOLDER : Folder to store config (default: $appdata/gabin/database.json)

Video mixers options

  • OBS : Gabin communicates directly with OBS via websocket to trigger shots and listen to scene change (needs OBS v28+)
  • VMIX : Gabin communicates directly with VMIX via TCP socket to trigger shots and listen to scene change
  • OSC : Gabin will triggers the paths you indicate for each shot and listen to scene change on his OSC port (more details below)

OSC API/module

By default, Gabin listen OSC on localhost:32123

API

Even if you don't choose OSC as video mixer, you can control Gabin through OSC

Command :

path params description
/gabin/on none power Gabin on
/gabin/off none power Gabin off
/gabin/config config: string add or edit this config
/gabin/profile profileName: string set this profile as active
/scene/$NAME_OF_YOUR_SCENE none tell Gabin what the current scene is
/source/$NAME_OF_YOUR_SOURCE none trigger a specific shot
/mic/$NAME_OF_YOUR_MIC availabe: 1,0 toggle mic availability
/autocam autocam: 1,0 toggle autocam

Request :

path params description
/gabin/is-ready host: string, port: number, path: string get TRUE if Gabin is connected
/gabin/profiles host: string, port: number, path: string get all profiles
/gabin/devices host: string, port: number, path: string get all audio devices

Register :

path params description
/register/shot host: string, port: number, path: string get updated on each triggered shot
/register/autocam host: string, port: number, path: string get updated when play/pause Gabin
/register/defaultProfile host: string, port: number, path: string get updated when new default profile is set

Other options

  • allow shot to be in scene but prevent from showing automatically

In the json database, go under profiles > settings > autocam > containers > mics > cams > source > options. There you can add a noIllu options, a boolean (true or false)

  • allow/forbid some shots depending on which mics are availables

In the json database, go under profiles > settings > autocam > containers > mics > cams > source > options. There you can add a matching options, the value must be a array of strings. You have to specify for each mics either :

  • the mic number : it has to be available
  • - : it has to be not available
  • * : the availability does not matter

E.g.:

profiles > settings > autocam > containers > mics > cams > source > options
[...]
{
  "source": {
    "name": "large shot 1",
    "options": {
      "matching": ["1234"]
    }
  },
  "weight": 5
},
{
  "source": {
    "name": "large shot 2",
    "options": {
      "matching": ["1*3-"]
    }
  },
  "weight": 10
},
[...]

The "large shot 1" may be shot if all the 4 mics are availables. Here, the "large shot 2" may be shot if :

  • the 1st and the 3rd mics are availables
  • the 4th mic is not available

Made in 🇫🇷 by OneClickStudio.

gabin's People

Contributors

bdebon avatar michael-dm avatar tillderoquefeuil 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  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

gabin's Issues

clarify "Probability", "Min", "Max"

These are unclear :

Screenshot 2023-01-17 at 15 15 52

We could add a small circled "i" (for information) after this 3 column titles. They would show a tooltip on hover like #4 with respective texts :

  • Describes how often this camera will be shown (between 0 and 100%)
  • Minimum duration a camera is shown. 0s will allow ugly glitches.
  • Maximum duration a camera is shown before changing to other available camera angles. Not useful if no other cameras are enabled for this mic.

clarify channel selection

It is unclear what these 2 options are :
Screenshot 2023-01-17 at 13 10 37

Idea :
Replace "Mic 1"... with "Channel 1"...

Add a tooltip (with HeadlessUI popover for ex) saying on hover : "Add this channel as a Mic."
Replace input label "Mic 1 Custom Name" with "Channel 1 Name".

[BUG] serveur tcp

salut, je voulais voir ce que c'est http://127.0.0.1:6481/ et j'ai eu cette erreur ;)

vous devez regarder si c'est bien du json avant de le parse.
c'est dans ce fichier: https://github.com/one-click-studio/gabin/blob/main/src/main/servers/TcpServer.ts

socket.on('data', (data: Buffer) => {
  const request: TcpRequest = JSON.parse(data.toString()) //ici
  if (!request.type){
     this.logger.error('received request without type', request)
     return
 }
 this.logger.debug('received request', request)
 this.sendRequestToClients(request)
});

image

refresh OBS scenes

If you add / edit scenes too late, they don't appear here :
Screenshot 2023-01-17 at 13 52 37

There should be a 🔄 button (I had to completely restart the app).

[API/Settings] Remote control to edit a profile

Inside a studio where hosts may move at different places, is there any possibility to easily change the shot associated to a mic source without having to edit a profile?

It may be interesting to control this kind of assignations, so it can be controlled by remote devices like Companion or custom Raspberry Pi devices.

Documentation protocole OSC

Bonjour,

Je vois que la version 0.3 de Gabin sera en mesure de se connecter à un serveur OSC.
J'envisage de développer un genre de middleware entre OBS et Gabin, qui communiquerait en OSC, pour répondre à 2 problématiques :

  • Pouvoir changer les assignations de l'activité audio aux différents plans de caméras ( → si quelqu'un change de place en cours de live)
  • Pouvoir déclencher un changement de plan (qui serait demandé par Gabin) dans OBS, après que la caméra concernée (PTZ) a fini de se réorienter.

Ma question : est-ce que l'API pour que Gabin puisse se brancher en OSC est / sera documentée quelque part ?

Merci :)

Minor fixes

  • x to close modal
  • probabilities all at 100% in summary view
  • OSC marked as not connected in running view
  • disconnect view not triggered when in running view

[UI/UX] Exit the profile editor

Currently, to exit the profile editor, we need to click "Cancel".

It may not be clear because of the meaning of "Cancel", even after having saved the profile changes.

Is it possible to add a close button to the top right corner of the editor, that will have the same role than the cancel button?

Camlock Logic

If next shot is the same as before, do not lock the container.

(+ minor unfocus bug)

buttons feedback on click

We should have a feedback when clicking on buttons. (a different level of opacity than hover for instance)

check OBS version

When connecting to OBS, check if version >= 28 and show error if not.

change edit menu

Remove timeline & useless steps. Allow quick edits on mappings.

check if obs connection is valid

During initial setup (when setting OBS ip & password), a check should be made that connection is valid.
If not, show error & prevent going forward.

(pre-release 0.2.5) Crash au moment de lancer l'autocam

Après avoir configuré mon profil dans la pre-release 0.2.5, l'application a crashé.

La configuration était établie comme suit :

  • Connexion ASIO à ReaRoute (Reaper)
  • 4 canaux ASIO utilisés en entrée
  • Dans OBS, 2 conteneurs avec chacun d'entre eux les 3 mêmes caméras
  • Dans OBS, 2 scènes, la première avec 1 seul conteneur, la deuxième avec 2 conteneurs
  • Le reste des réglages (durée des scènes, affectations des caméras…) dans Gabin sont les réglages par défaut

Voici la trace des logs :

01:37:32 [Gabin - main process 🤖] New gabin client connected 2023-05-26 01:37:32.0962139 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0966568 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.0968680 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0973148 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0975061 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0978603 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.0980087 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0983212 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0984340 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.0985649 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2137832 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2139599 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2142208 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.2143900 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2147683 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2151971 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2153912 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2155519 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.2156992 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.2158312 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3046578 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3048366 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3049589 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3051386 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.3053454 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3058453 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3059883 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3061775 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3063369 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3064997 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3944424 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '620'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.3949175 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '623'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3952927 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '625'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3954763 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '629'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] R[1] 2023-05-26 01[1] 2023-05-26 01:37:32.3956181 [W[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitiali[1] 2023-05-26 01:37:32.3956181[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitia[1] 2023-05-26 01:37:32.3956[1] 2023-05-26 01:37:32.3956[1] 2023-05-26[1] 2023-05-26[1] 2023-05-26 01:37:32.3956[1] 2023-05-26[1] 2023-05-26[1] 2023-05-26[1] 2023-05-26 01:37:32.3956181 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '628'. It is not used by any node and should be removed from the model.
2023-05-26 01:37:32.3959201 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '131'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3961775 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '134'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3962915 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '136'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3964072 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '140'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.3965608 [W:onnxruntime:, graph.cc:3490 onnxruntime::Graph::CleanUnusedInitializersAndNodeArgs] Removing initializer '139'. It is not used by any node and should be removed from the model.
[1] 2023-05-26 01:37:32.4484837 [E:onnxruntime:, sequential_executor.cc:494 onnxruntime::ExecuteKernel] Non-zero status code returned while running Pad node. Name:'Pad_63' Status Message: Cannot use 'reflect' mode to pad dimension with a value of 0. Input shape:{1,1,1,0}
2023-05-26 01:37:32.4490770 [E:onnxruntime:, sequential_executor.cc:494 onnxruntime::ExecuteKernel] Non-zero status code returned while running If node. Name:'If_25' Status Message: Non-zero status code returned while running Pad node. Name:'Pad_63' Status Message: Cannot use 'reflect' mode to pad dimension with a value of 0. Input shape:{1,1,1,0}     [1]
[1] 01:37:32 [Gabin - main process 🤖] Error: Non-zero status code returned while running If node. Name:'If_25' Status Message: Non-zero status code returned while running Pad node. Name:'Pad_63' Status Message: Cannot use 'reflect' mode to pad dimension with a value of 0. Input shape:{1,1,1,0}
[1]     at C:\***\gabin\node_modules\.pnpm\[email protected]\node_modules\onnxruntime-node\lib\backend.ts:41:42
    at processTicksAndRejections (node:internal/process/task_queues:77:11)
[1] 01:37:32 [Gabin - main process 🤖] Cleaning...
01:37:32 [Gabin - main process 🤖] Client disconnected ***
01:37:32 [osc-server] osc-server server disconnected
01:37:32 [osc-server] cleaning osc-server server [nodemon] app crashed - waiting for file changes before starting...

fix build

We must find a clean way to find this pnpm.cjs file and patch it in release.yml.
This currently prevents builds to work.

[API] Remote control?

I see that Gabin may be connected to a "Companion" device. Is there any documentation anywhere to see what features may be controlled by a remote controller?

cropped container step

If window is not wide enough, it crops this step horizontally :

Screenshot 2023-01-17 at 13 30 12

Add overflow-y or prevent content being > 100%.

default camera selection toggle

On "Auto cam settings" panel, default config should be :

  • for each mic, one of the camera is selected, at 100% probability (or none if all are selected in other mics)

Not : every cam is enabled for every mic.

Make sure that "Reset all" button follows this too.

minor UI fixes

  1. should be aligned

Screenshot 2023-01-17 at 15 39 34

  1. should have capital I for "I'm" -> no idea where this message is lowercased

Screenshot 2023-01-17 at 15 40 05

  1. there are small lags when starting / stopping Gabin, we should have an instant transition (with loading / skeletons if necessary)

  2. this menu should not have rounded corners

Screenshot 2023-01-17 at 15 43 45

  1. arrow should be vertically aligned with +

Screenshot 2023-01-17 at 15 45 05

  1. some texts line-heights are very low, and make them hard to read :

Screenshot 2023-01-17 at 16 45 57

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.