Giter Site home page Giter Site logo

send-to-kodi's People

Contributors

allejok96 avatar khalahan 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

Watchers

 avatar  avatar  avatar  avatar  avatar

send-to-kodi's Issues

MPEG-DASH support

Hello,

First I'd like to say it's very nice and powerfull script, yet simple and short.
Have you considered sending separate video and audio stream? Is it even possible with json-rpc kodi API?

Currently if I use the script it sends only 320p combined stream which is really poor. However with default action youtube-dl selects 720p but then these are separate video&audio streams.
Current youtube-dl usage by script:

youtube-dl -gf best 'https://www.facebook.com/watch/live/?v=190790559367200&ref=watch_permalink'
https://scontent.fwaw5-1.fna.fbcdn.net/v/t66.36281-6/10000000_907241116478824_1982327047256291720_n.mp4?_nc_cat=111&ccb=2&_nc_sid=985c63&efg=eyJ2ZW5jb2RlX3RhZyI6Im9lcF9zZCJ9&_nc_ohc=PTfIAsDM1AQAX-ltN9e&_nc_ht=scontent.fwaw5-1.fna&oh=50047fc087406a04a5171c254a61acb7&oe=5FF26A0A

Best quality 720p but 2 separate streams

youtube-dl -g 'https://www.facebook.com/watch/live/?v=190790559367200&ref=watch_permalink'
https://video.fwaw5-1.fna.fbcdn.net/v/t58.24163-29/10000000_374104710550142_4622832835349334323_n.mp4?_nc_cat=108&ccb=2&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfbGl2ZV9oZDFfdW1hX2ZyYWdfMl92aWRlbyJ9&_nc_ohc=WP8B6o5LAe8AX_82cWM&_nc_ht=video.fwaw5-1.fna&oh=b2fdcfe3830940c0095d39992e5ddd4e&oe=5FCF5E6E
https://video.fwaw5-1.fna.fbcdn.net/v/t58.24163-29/10000000_803469820218481_3195184083453920485_n.mp4?_nc_cat=104&ccb=2&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfbGl2ZV9tZF91bWFfZnJhZ18yX2F1ZGlvIn0=&_nc_ohc=fISeck7tShoAX_xZei2&_nc_ht=video.fwaw5-1.fna&oh=af7fe1ac18f037f50eb531792ca1022b&oe=5FCFB9CF

Not an issue, you can use ADB to play files on kodi

Without needing to enable the Kodi http server, you can use:

adb shell am start -a android.intent.action.VIEW -d "$URL" org.xbmc.kodi/.Splash

I'll leave a little script I've made.

  • It plays youtube on "com.liskovsoft.smarttubetv.beta"
  • It plays twitch or m3u8 on MXplayer (or VLC)
  • It plays other urls on MXplayer (or VLC)
  • It plays local video files, serving them with a python http webserver made with flask (python code is inlined). It transcodes the video if its bigger than 1080p (I have a Chromecast HD)
#!/bin/bash

function is_tv_connected() { 	#adb doesn't give good exit codes :(
	TV_IP="$(avahi-browse -r -kt  _googlecast._tcp |sed -nE 's/.*\[([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\].*/\1/p' | head -n1)"
	#TV_IP=$(resolvectl query Android.local -4 --legend=false | sed -n 's/.* \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p' | head -n1)
	echo "[INFO] Chromecast ip address: $TV_IP"
	adb connect "$TV_IP" 1>/dev/null
	if adb get-state | grep "device" 1>/dev/null ; then
		echo '[INFO] Device is connected'
		return 0
	else
		echo '[ERROR] no device connected! or unauthorized (check TV)'
		return 1
	fi
}

function kill_app(){ #[PKGNAME]
	GETPKGNAME=$(adb shell pm list packages | grep -i "$1" | awk -F':' '{print $2}' | tr -d '[:space:]')
	adb shell am force-stop "${GETPKGNAME}"
}

function androidrun() { #PKGNAME #URL
	#Get app pkgname
	GETPKGNAME=$(adb shell pm list packages | grep -i "$1" | awk -F':' '{print $2}' | tr -d '[:space:]')
  PKGNAME="${GETPKGNAME:-com.google.android.youtube.tv}"
  echo "[INFO] Playing video on $PKGNAME"
	adb shell am force-stop "${PKGNAME}"
	#adb shell am start -a android.intent.action.VIEW --activity-clear-task -d "$2" "${PKGNAME}"
	if [[ "${PKGNAME}" == org.xbmc.kodi ]]; then
		adb shell am start -a android.intent.action.VIEW -d "$2" "${PKGNAME}"/.Splash
	else
		adb shell am start -a android.intent.action.VIEW -d "$2" "${PKGNAME}"
	fi
}

function webserver(){ #[Filepath to serve on /video.mkv]
python - "$1" <<END
import os, re, sys
from flask import Flask, Response, request

app = Flask(__name__)

@app.route('/video.mkv')
def get_video():
    filename = sys.argv[1] if len(sys.argv) > 1 else 'video.mkv'
    filesize = os.path.getsize(filename)
    range_header = request.headers.get('Range', None)

    if range_header:
        byte1, byte2 = 0, None
        match = re.search(r'(\d+)-(\d*)', range_header)
        groups = match.groups()

        if groups[0]:
            byte1 = int(groups[0])
        if groups[1]:
            byte2 = int(groups[1])

        if byte2 is not None:
            if byte2 > filesize - 1:
                byte2 = filesize - 1

        length = byte2 - byte1 if byte2 is not None else filesize - byte1

        with open(filename, 'rb') as f:
            f.seek(byte1)
            data = f.read(length)
        
        resp = Response(
            data, status=206, mimetype='video/x-matroska',
            content_type='video/x-matroska', direct_passthrough=True
        )

        resp.headers.add('Content-Range',
                         'bytes {0}-{1}/{2}'
                         .format(byte1, byte1 + length - 1, filesize))
        resp.headers.add('Accept-Ranges', 'bytes')
        return resp

    return Response(
        open(filename, 'rb').read(), status=200, mimetype='video/x-matroska'
    )


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=5000,debug=False)

END
	
}
### Main

#Check dependencies
command -v ffmpeg >/dev/null 2>&1 || { echo >&2 "I require ffmpeg but it's not installed.  Aborting."; exit 1; }
command -v adb >/dev/null 2>&1 || { echo >&2 "I require adb but it's not installed.  Aborting."; exit 1; }
command -v ip >/dev/null 2>&1 || { echo >&2 "I require ip but it's not installed.  Aborting."; exit 1; }
command -v yt-dlp >/dev/null 2>&1 || { echo >&2 "I require yt-dlp but it's not installed.  Aborting."; exit 1; }

#Help and usage
if [[ "$*" =~ "--help" ]] || [[ "$*" =~ "-h" ]] || [[ $# -eq 0 ]]; then
  #printf "Usage:\n\t[URL]\n\tkill [APP NAME]\n"
  printf """Usage: 
  [FILE OR URL] : Plays the local file or URL on the Chromecast.
  kill [appname] : kills the appname. fuzzy search of the nane.
"""
  exit 0
elif [[ "$1" =~ "kill" ]]; then
	kill_app "$2"
	exit 0
fi 


if echo "$1" | grep -P "^(https?):\/\/[^\s/$.?#].[^\s]*$" > /dev/null; then #Check valid URL
	if is_tv_connected; then
		adb shell input keyevent KEYCODE_WAKEUP #Wake up TV

		if [[ "$1" =~ (youtube.com|youtu.be) ]]; then
			androidrun smarttubetv "$1" #Play youtube video
			exit
		elif [[ "${1}" =~ (twitch.tv|m3u8) ]]; then
			URL=$(yt-dlp --get-url "$1")
			androidrun mxtech "$URL"
			exit
		else
			URL=$(yt-dlp --get-url "$1")
			androidrun mxtech "$URL"
			exit
		fi
	fi
else
	if [ -f "$1" ]; then #check if argv is a valid path to a file
		if is_tv_connected; then
			adb shell input keyevent KEYCODE_WAKEUP #Wake up TV
	    
	    video_file="$1"
	    
	    # Use ffprobe to get the video resolution
	    resolution=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 "$video_file")
	    
	    # Extract width and height from the resolution output
	    width=$(echo "$resolution" | cut -d 'x' -f1)
	    height=$(echo "$resolution" | cut -d 'x' -f2)
	    
	    # Check if the video resolution is larger than 1920x1080
	    if [ "$width" -gt 1920 ] && [ "$height" -gt 1080 ]; then
	      echo "[INFO] The video is larger than 1920x1080. Transcoding"

	      TEMP_VIDEO=$(mktemp --suffix=.mkv)

	      ## Burn subtitles: -vf "scale=1920:-2,subtitles=${video_file}:stream_index=0:force_style='FontName=Droid Sans,Fontsize=12'"
				ffmpeg -nostdin -hide_banner -loglevel quiet -y \
					-hwaccel cuda \
					-i "${video_file}" -c:v hevc_nvenc -b:v 5M -c:a libopus -b:a 128k -ac 2 -pix_fmt yuv420p \
					-vf "scale=1920:-2" \
					-f matroska -movflags faststart -strict -2 \
					"${TEMP_VIDEO}" &

				sleep 1

				webserver "${TEMP_VIDEO}" &
				IP=$(ip -4 addr show | grep -oP "(?<=inet ).*(?=/)" | tail -n1)
				androidrun kodi "http://$IP:5000/video.mkv"
	    else
	      echo "[INFO] The video is not larger than 1920x1080."
	        
				webserver "${video_file}" &
				IP=$(ip -4 addr show | grep -oP "(?<=inet ).*(?=/)" | tail -n1)
				androidrun kodi "http://$IP:5000/video.mkv"
	    fi
	    
	   fi
	else
	    echo "[ERROR] The path $1 is either not a file or doesn't exist."
	fi
fi


function exit_handler(){
	jobs -p | xargs -r kill
	if [ -n "$TEMP_VIDEO" ]; then
		rm -f "$TEMP_VIDEO"
	fi
	kill_app kodi
	kill 0
	echo "Finished cleaning up."
}

trap "exit" INT TERM
trap exit_handler EXIT

#Wait until control+C
echo "Control+C to quit"
read -r _

exit_handler

exit

Kodi youtube notification: UNKNOWN

I love the idea of this script! However, when I run it I see Kodi respond with a notification saying "unknown".
In terminal I get this response: {"id":1,"jsonrpc":"2.0","result":"OK"}
Used a normal youtube link, running mac Catalina.

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.