Using (modified) pykodi and uc-integration-api
The driver lets discover and configure your Kodi instances. A media player and a remote entity are exposed to the core.
Note : this release requires remote firmware >= 1.7.10
- Installation
- Additional commands
- Note about Kodi keymap and UC Remotes
- Installation as external integration
- Build self-contained binary for Remote Two
Media Player entity
- State (on, off, playing, paused, unknown)
- Title
- Album
- Artist
- Artwork
- Media position / duration
- Volume (level and up/down) and mute
- Sources : corresponds to the list of video chapters (Kodi >=22 only)
Remote entity
- Predefined buttons mapping and interface buttons
- State (On / Off)
Sensors Several sensors are available with the following attributes exposed :
- Current audio stream name
- Current subtitle stream name
- Current chapter name (Kodi >=22)
- Current video information (resolution, codec)
- Current volume level
- Current volume muted state
Note: the audio/subtitle streams names are available prior Kodi 22 but are not updated instantly (I pushed a patch recently in Kodi 22 to get instant updates)
- Turn off (turn on is not supported)
- Direction pad and enter
- Numeric pad
- Back
- Next
- Previous
- Volume up
- Volume down
- Pause / Play
- Channels Up/Down
- Menus (home, context)
- Colored buttons
- Subtitle/audio language switching
- Fast forward / rewind
- Stop
- Source selection : corresponds to chapters selection (Kodi >=22 only)
- Simple commands (more can be added) : see list of simple commands
- Send command : custom commands or keyboard commands which sent as KB keymap commands in JSON RPC (see Kodi keyboard map and more specifically Action Ids for the list of available keyboard commands)
Example : type in
togglefullscreenin the command field of the remote entity to toggle full screen - Send command sequence (same commands as above)
- Support for the repeat, hold, delay parameters
- List of commands (simple or custom) : see the list here
- First go to the release section and download the
xxx_aarch64-xxx.tar.gzfile - On the Web configurator of your remote, go to the
Integrationstab, click onAdd newand selectInstall custom - Select the downloaded file in first step and wait for the upload to finish
- A new integration will appear in the list : click on it and start setup
- Kodi must be running for setup, and control enabled from Settings > Services > Control section. Set the username, password and enable HTTP control.
- Port numbers shouldn't be modified normally (8080 for HTTP and 9090 for websocket) : websocket port is not configurable from the GUI (in advanced settings file)
- There is no turn on command : Kodi has to be started some other way
General info : if the direction pad doesn't work, enable the Joystick extension in Kodi settings then exit (not just minimize) Kodi and relaunch it.
On Kodi 22 :
- in fullscreen video the
OKbutton will trigger play/pause instead of the default behavior which should trigger OSD menu - in the navigation menus the
Backbutton will go back to the home instead of the previous menu I raised a ticket for that. In the meantime to restore this default behavior, you will have to create ajoystick.xmlfile with the following content :
<keymap>
<global>
<joystick profile="game.controller.default">
<back>Back</back>
</joystick>
</global>
<fullscreenvideo>
<joystick profile="game.controller.default">
<a>OSD</a>
</joystick>
</fullscreenvideo>
</keymap>Then you will have to transfer this file through Kodi Settings > File manager into the Profile directory then keymaps directory : mount a network share or use a USB stick to grab it

See the target path in the bottom like this :

Then on the right view, from your server (NAS, PC...) right click (or long press OK) to raise context menu and select Copy on the joystick.xml file to transfer it to the server.
Lastly, exit Kodi (not just minimize) and relaunch it.
On Kodi 21 and earlier, this is easier : within Kodi, click settings, then go to Apps/Add-on Browser, My Add-ons and scroll down and click on Peripheral Libraries : click on Joystick Support and click Disable. THEN : kill and restart Kodi in order to take effect and then all the remote commands will work fine.
To save battery life, the integration will stop reconnecting if Kodi is off (which is the case on most devices when you switch from Kodi to another app). But if any Kodi command is sent (cursor pad, turn on, play/pause...), a reconnection will be automatically triggered.
So if you start Kodi (ex : from Nvidia Shield), but you mapped all cursors pad and enter to Nvidia Shield device (through AndroidTV integration or bluetooth), Kodi reconnection won't be triggered. So here is the trick to make Kodi integration reconnect : create a macro with your devices (e.g. Nvidia Shield, and Kodi media player) with the following commands :
- Nvidia Shield :
Input Sourcecommand to start appKodi - Kodi media player :
Switch Oncommand (which does nothing except triggering reconnection)
And add the macro to your activity, mapped to the screen or to a button. In that way, it will both launch Kodi and trigger the reconnection.
- Download the release from the release section : file ending with
.tar.gz - Navigate into the Web Configurator of the remote, go into the
Integrationstab, click onAdd newand select :Install custom - Select the downloaded
.tar.gzfile and click on upload - Once uploaded, the new integration should appear in the list : click on it and select
Start setup - Your Kodi instance must be running and connected to the network before proceed
The integration lets backup or restore the devices configuration (in JSON format). To use this functionality, select the "Backup or restore" option in the setup flow, then you will have a text field which will be empty if no devices are configured.
- Backup : just save the content of the text field in a file for later restore and abort the setup flow (clicking next will apply this configuration)
- Restore : just replace the content by the previously saved configuration and click on next to apply it. Beware while using this functionality : the expected format should be respected and could change in the future. If the format is not recognized, the import will be aborted and existing configuration will remain unchanged.
First don't mix up with entities : when registering the integration, you will get 2 entities : Media Player and Remote entities.
The media player entity should cover most needs, however if you want to use custom commands and use additional parameters such as repeating the same command, you can use the remote entity.
This entity exposes 2 specific commands : Send command and Command sequence
Here is an example of setting a Send command command from the remote entity :
These are exposed by both media & remote entities :
| Simple command | Description |
|---|---|
| MENU_VIDEO | Show video menu (showvideomenu) |
| MODE_TOGGLE_GUI | Toggle GUI while playing |
| MODE_FULLSCREEN | Toggle full screen (togglefullscreen) |
| MODE_SHOW_AUDIO_STREAM | Show audio streams menu while playing (Kodi >=22) |
| MODE_SHOW_SUBTITLES_STREAM | Show subtitles streams menu while playing (Kodi >=22) |
| MODE_SHOW_AUDIO_MENU | Show audio context menu while playing |
| MODE_SHOW_SUBTITLES_MENU | Show subtitles context menu while playing |
| MODE_SHOW_VIDEO_MENU | Show video settings menu while playing |
| MODE_SHOW_BOOKMARKS_MENU | Show bookmarks menu while playing |
| MODE_SHOW_SUBTITLE_SEARCH_MENU | Show subtitles search menu while playing |
| MODE_SCREENSAVER | Show screensaver |
| MODE_ZOOM_IN | Zoom in (zoomin) |
| MODE_ZOOM_OUT | Zoom out (zoomout) |
| MODE_INCREASE_PAR | Increase aspect ratio (increasepar) |
| MODE_DECREASE_PAR | Decrease aspect ratio (decreasepar) |
| MODE_SHOW_SUBTITLES | Toggle subtitles (showsubtitles) |
| MODE_SUBTITLES_DELAY_MINUS | Decrease subtitles delay (subtitledelayminus) |
| MODE_SUBTITLES_DELAY_PLUS | Increase subtitles delay (subtitledelayplus) |
| MODE_AUDIO_DELAY_MINUS | Decrease audio delay (audiodelayminus) |
| MODE_AUDIO_DELAY_PLUS | Increase audio delay (audiodelayplus) |
| MODE_DELETE | Delete (delete) |
| APP_HIBERNATE | Hibernate the device (System.Hibernate) |
| APP_REBOOT | Reboot the device (System.Reboot) |
| APP_SHUTDOWN | Shutdown the device (System.Shutdown) |
| APP_SUSPEND | Suspend the device (System.Suspend) |
| ACTION_BLUE | Blue command |
| ACTION_GREEN | Green command |
| ACTION_RED | Red command |
| ACTION_YELLOW | Yellow command |
| System.Hibernate | Hibernate the device |
| System.Reboot | Reboot the device |
| System.Shutdown | Shutdown the device |
| System.Suspend | Suspend the device |
The following commands are standard commands available for the remote entity in addition of simple commands. These are already exposed by the Media Player entity through a predefined mappping but can also be used in the remote entity (to build commands sequence for example) :
on, off, toggle, play_pause, stop, previous, next, fast_forward, rewind, seek, volume, volume_up, volume_down, mute_toggle, mute, unmute, repeat, shuffle, channel_up, channel_down, cursor_up, cursor_down, cursor_left, cursor_right, cursor_enter, digit_0, digit_1, digit_2, digit_3, digit_4, digit_5, digit_6, digit_7, digit_8, digit_9, function_red, function_green, function_yellow, function_blue, home, menu, context_menu, guide, info, back, select_source, select_sound_mode, record, my_recordings, live, eject, open_close, audio_track, subtitle, settings, search
Additionally, the following custom commands can be set in the Send command or Command sequence commands of the Remote entity.
Some can have parameters
| Custom command | Description | Example |
|---|---|---|
key button [keymap (default KB)] [hold time (default 0)] |
Trigger keyboard command | key f KB 0key akey livetv R1 |
activatewindow windowId |
Show the given window ID, see this link | activatewindow movieinformation |
action action name |
Execute given action see the list here | action fastforward |
stereoscopimode mode |
Set the given stereoscopic mode, see here | stereoscopimode split_horizontal |
viewmode mode |
Set view mode : normal,zoom,stretch4x3,widezoom,stretch16x9,original, stretch16x9nonlin,zoom120width,zoom110width | viewmode stretch16x9 |
zoom mode |
Set zoom to given mode : in, out or level from 1 to 10 | zoom in |
speed speed |
Set playback speed : increment, decrement or integer from -32, -16, -8,... to 32 | speed 32 |
audiodelay offset |
Set audio delay in seconds relatively | audiodelay -0.1 |
<JSON RPC Command> {parameters} |
Any JSON RPC command complete list here Length is limited to 64 characters |
See examples below |
Execute action : list of actions here
- Show video menu :
Input.ExecuteAction {"action":"showvideomenu"} - Increase subtitles delay :
Input.ExecuteAction {"action":"subtitledelayplus"} - Decrease subtitles delay :
Input.ExecuteAction {"action":"subtitledelayminus"}
Shutdown the system :
System.Shutdown
Restart the system :
System.Restart
Increase audio delay :
Player.SetAudioDelay {"playerid":PID,"offset":"increment"}
Decrease audio delay :
Player.SetAudioDelay {"playerid":PID,"offset":"decrement"}
Set audio delay to +0.5 seconds :
Player.SetAudioDelay {"playerid":PID,"offset":0.5}
Notes :
- Some commands require a player Id parameter, just submit
PIDvalue that will be evaluated on runtime - Commands length if limited to 64 characters
With the UC remote, the button mapping is not Kodi's default with other devices (eg original AndroidTV remote). This is very obscure but in the meantime it is possible to catch the button IDs and remap them.
- First, in Kodi settings, go to System / Logs and enable debug mode
- Press the buttons you want to catch from the remote
- Disable debug log when finished
- Go to Settings / File explorer, go to logpath and you will find
kodi.log - Transfer
kodi.logto your external drive (NAS, USB flashdrive...)
You will find lines like these :
FEATURE [ back ] on game.controller.default pressed (handled)
FEATURE [ up ] on game.controller.default pressed (handled)
FEATURE [ a ] on game.controller.default pressed (handled)
The name between square brackets correspond to the button ID : here back for back, up for DPAD up, a for OK button.
Then you will be able to modify the Keyboard mapping as explained at the beginning of the document : define a custom keymap file joystick.xml and upload it to profile folder / keymaps.
A little explanation of how it works :
globalsection defines the default mapping in navigationfullscreenvideosection defines the mapping applied while playing a video in fullscreen- Subsections define the device type to apply mapping to :
keyboard,mouse,gamepadandjoystick. Note that the UC remote is detected as a joystick so other types won't be applied - Lastly, in the
joysticksubsection, define the custom mapping : the button ID in the tag (eg<a>...</a>for OK button), and the command to apply. See this link to get the list of commands
<keymap>
<global>
<joystick profile="game.controller.default">
<back>Back</back>
</joystick>
</global>
<fullscreenvideo>
<joystick profile="game.controller.default">
<a>OSD</a>
</joystick>
</fullscreenvideo>
</keymap>- Requires Python 3.11
- Under a virtual environment : the driver has to be run in host mode and not bridge mode, otherwise the turn on function won't work (a magic packet has to be sent through network and it won't reach it under bridge mode)
- Your Kodi instance has to be started in order to run the setup flow and process commands. When configured, the integration will detect automatically when it will be started and process commands.
- Install required libraries:
(using a virtual environment is highly recommended)
pip3 install -r requirements.txtFor running a separate integration driver on your network for Remote Two, the configuration in file driver.json needs to be changed:
- Set
driver_idto a unique value,uc_kodi_driveris already used for the embedded driver in the firmware. - Change
nameto easily identify the driver for discovery & setup with Remote Two or the web-configurator. - Optionally add a
"port": 8090field for the WebSocket server listening port.- Default port:
9090 - Also overrideable with environment variable
UC_INTEGRATION_HTTP_PORT
- Default port:
python3 src/driver.pySee available environment variables in the Python integration library to control certain runtime features like listening interface and configuration directory.
After some tests, turns out python stuff on embedded is a nightmare. So we're better off creating a single binary file that has everything in it.
To do that, we need to compile it on the target architecture as pyinstaller does not support cross compilation.
On x86-64 Linux we need Qemu to emulate the aarch64 target platform:
sudo apt install qemu binfmt-support qemu-user-static
docker run --rm --privileged multiarch/qemu-user-static --reset -p yesRun pyinstaller:
docker run --rm --name builder \
--platform=aarch64 \
--user=$(id -u):$(id -g) \
-v "$PWD":/workspace \
docker.io/unfoldedcircle/r2-pyinstaller:3.11.6 \
bash -c \
"python -m pip install -r requirements.txt && \
pyinstaller --clean --onefile --name driver src/driver.py"On an aarch64 host platform, the build image can be run directly (and much faster):
docker run --rm --name builder \
--user=$(id -u):$(id -g) \
-v "$PWD":/workspace \
docker.io/unfoldedcircle/r2-pyinstaller:3.11.6 \
bash -c \
"python -m pip install -r requirements.txt && \
pyinstaller --clean --onefile --name driver src/driver.py"For easy installation on x86-64 and ARM64 systems using Docker:
# Clone repository
git clone https://github.com/albaintor/integration-kodi.git
cd integration-kodi
# Start with Docker Compose
docker-compose up -d
# View logs
docker-compose logs -f# Build and start
make start
# View logs
make logs
# Stop
make down
# Restart
make restart# Pull and run from Docker Hub
docker run -d \
--name kodi-integration \
--network host \
-v $(pwd)/config:/app/config \
-e UC_INTEGRATION_HTTP_PORT=9090 \
docker.io/your-username/kodi-integration:latest# Build image locally
docker build -t kodi-integration .
# Run container
docker run -d \
--name kodi-integration \
--network host \
-v $(pwd)/config:/app/config \
-e UC_INTEGRATION_HTTP_PORT=9090 \
kodi-integration- Integration runs on port
9090(configurable viaUC_INTEGRATION_HTTP_PORT) - Configuration data is stored in
./configdirectory network_mode: hostis required for network discovery and magic packets- Supports both x86-64 and ARM64 architectures
After startup, the integration is available at http://localhost:9090 and can be configured in Remote Two/Three.
latest- Latest development build from main branchv1.x.x- Specific version releasesmain- Latest commit from main branch
Pre-built images are available on Docker Hub with multi-architecture support (x86-64 and ARM64).
We use SemVer for versioning. For the versions available, see the tags and releases in this repository.
The major changes found in each new release are listed in the changelog and under the GitHub releases.
Please read our contribution guidelines before opening a pull request.
This project is licensed under the Mozilla Public License 2.0. See the LICENSE file for details.