Last night, I wrote a recipe to stream a Linux desktop using VLC to a instance of Kodi. During the day I received valuable feedback, and thanks to the suggestions I have been able to rewrite the recipe into a much simpler approach requiring no setup at all. It is a single script that take care of it all.
This new script uses GStreamer instead of VLC to capture the desktop and stream it to Kodi. This fixed the video quality issue I saw initially. It further removes the need to add a m3u file on the Kodi machine, as it instead connects to the JSON-RPC API in Kodi and simply ask Kodi to play from the stream created using GStreamer. Streaming the desktop to Kodi now become trivial. Copy the script below, run it with the DNS name or IP address of the kodi server to stream to as the only argument, and watch your screen show up on the Kodi screen. Note, it depend on multicast on the local network, so if you need to stream outside the local network, the script must be modified. Also note, I have no idea if audio work, as I only care about the picture part.
#!/bin/sh # # Stream the Linux desktop view to Kodi. See # https://people.skolelinux.org/pere/blog/Streaming_the_Linux_desktop_to_Kodi_using_VLC_and_RTSP.html # for backgorund information. # Make sure the stream is stopped in Kodi and the gstreamer process is # killed if something go wrong (for example if curl is unable to find the # kodi server). Do the same when interrupting this script. kodicmd() { host="$1" cmd="$2" params="$3" curl --silent --header 'Content-Type: application/json' \ --data-binary "{ \"id\": 1, \"jsonrpc\": \"2.0\", \"method\": \"$cmd\", \"params\": $params }" \ "http://$host/jsonrpc" } cleanup() { if [ -n "$kodihost" ] ; then # Stop the playing when we end playerid=$(kodicmd "$kodihost" Player.GetActivePlayers "{}" | jq .result[].playerid) kodicmd "$kodihost" Player.Stop "{ \"playerid\" : $playerid }" > /dev/null fi if [ "$gstpid" ] && kill -0 "$gstpid" >/dev/null 2>&1; then kill "$gstpid" fi } trap cleanup EXIT INT if [ -n "$1" ]; then kodihost=$1 shift else kodihost=kodi.local fi mcast=239.255.0.1 mcastport=1234 mcastttl=1 pasrc=$(pactl list | grep -A2 'Source #' | grep 'Name: .*\.monitor$' | \ cut -d" " -f2|head -1) gst-launch-1.0 ximagesrc use-damage=0 ! video/x-raw,framerate=30/1 ! \ videoconvert ! queue2 ! \ x264enc bitrate=8000 speed-preset=superfast tune=zerolatency qp-min=30 \ key-int-max=15 bframes=2 ! video/x-h264,profile=high ! queue2 ! \ mpegtsmux alignment=7 name=mux ! rndbuffersize max=1316 min=1316 ! \ udpsink host=$mcast port=$mcastport ttl-mc=$mcastttl auto-multicast=1 sync=0 \ pulsesrc device=$pasrc ! audioconvert ! queue2 ! avenc_aac ! queue2 ! mux. \ > /dev/null 2>&1 & gstpid=$! # Give stream a second to get going sleep 1 # Ask kodi to start streaming using its JSON-RPC API kodicmd "$kodihost" Player.Open \ "{\"item\": { \"file\": \"udp://@$mcast:$mcastport\" } }" > /dev/null # wait for gst to end wait "$gstpid"
I hope you find the approach useful. I know I do.
As usual, if you use Bitcoin and want to show your support of my activities, please send Bitcoin donations to my address 15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b.