Support live streams
Now the type of a video is defined when trying to play a video so that live streams (.m3u8) are directly played by Kodi (no download required). We are able to know if a video is live from the response of the "list" REST API but it was decided to ignore this information in order to have a single action to play video (whether it is live or not). The goal was to keep the API of the add-on as simple as possible so that externel users only have to call the add-on's API with the ID of a video, without having to add the type of the video. The information about the type of the video will anyway be available in the response used to get the URL of a video so this solution does not impact the performance.
This commit is contained in:
parent
ed39c453e9
commit
4f8af35035
28
README.md
28
README.md
|
@ -2,21 +2,22 @@ A Kodi add-on for watching content hosted on [PeerTube](http://joinpeertube.org/
|
|||
|
||||
This add-on is under development so only basic features work, and you're
|
||||
welcome to improve it.
|
||||
See [contribution guidelines](contributing.md) and
|
||||
[pending issues](https://framagit.org/StCyr/plugin.video.peertube/-/issues) to
|
||||
start.
|
||||
If you want to contribute, please start with the
|
||||
[contribution guidelines](contributing.md) and the
|
||||
[pending issues](https://framagit.org/StCyr/plugin.video.peertube/-/issues).
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Features
|
||||
|
||||
* Browse all videos on a PeerTube instance
|
||||
* Play videos (including live videos)
|
||||
* Browse the videos on a PeerTube instance
|
||||
* Search for videos on a PeerTube instance
|
||||
* Select the PeerTube instance to use
|
||||
* Select the preferred video resolution: the plugin will try to play the select
|
||||
video resolution.
|
||||
* Select the preferred video resolution: the plugin will try to play the
|
||||
preferred video resolution.
|
||||
If it's not available, it will play the lower resolution that is the closest
|
||||
from your preference.
|
||||
to your preference.
|
||||
If not available, it will play the higher resolution that is the closest from
|
||||
your preference.
|
||||
|
||||
|
@ -24,9 +25,10 @@ start.
|
|||
|
||||
* Preferred PeerTube instance
|
||||
* Preferred video resolution
|
||||
* Number of videos to display per page
|
||||
* Sort method to be used when listing videos (Currently, only 'views' and
|
||||
'likes')
|
||||
* Number of items to display per page
|
||||
* Value used to sort items when listing/searching videos:
|
||||
* `views`: sort by number of views (ascending only)
|
||||
* `likes`: sort by number of likes (ascending only)
|
||||
* Select the filter to use when browsing the videos on an instance:
|
||||
* local will only display the videos which are local to the selected instance
|
||||
* all-local will only display the videos which are local to the selected
|
||||
|
@ -53,8 +55,10 @@ the add-on with:
|
|||
|
||||
* This add-on doesn't support Webtorrent yet. So, it cannot download/share
|
||||
from/to regular PeerTube clients.
|
||||
* The add-on doesn't delete the downloaded files at the moment. So, it may fill
|
||||
up your disk.
|
||||
* The add-on doesn't delete the downloaded files at the moment so it may fill
|
||||
up your disk. You may delete manually the downloaded files in the folder
|
||||
`<kodi_home>/temp/plugin.video.peertube/` (more information on `<kodi_home>`
|
||||
[here](https://kodi.wiki/view/Kodi_data_folder#Location)).
|
||||
|
||||
# Installation and prerequisites
|
||||
|
||||
|
|
|
@ -161,6 +161,14 @@ class PeerTubeAddon():
|
|||
data["thumbnailPath"]),
|
||||
aired=data["publishedAt"]
|
||||
)
|
||||
# Note: the type of video (live or not) is available in "response"
|
||||
# but this information is ignored here so that the "play_video"
|
||||
# action is the same whatever the type of the video. The goal is to
|
||||
# allow external users of the API to play a video only with its ID
|
||||
# without knowing its type.
|
||||
# The information about the type of the video will anyway be
|
||||
# available in the response used to get the URL of a video so this
|
||||
# solution does not impact the performance.
|
||||
|
||||
yield video_info
|
||||
else:
|
||||
|
@ -202,13 +210,18 @@ class PeerTubeAddon():
|
|||
return next_page_item
|
||||
|
||||
def _get_video_url(self, video_id, instance=None):
|
||||
"""Find the URL of the video with the best possible quality matching
|
||||
"""Return the URL of a video and its type (live or not)
|
||||
|
||||
Find the URL of the video with the best possible quality matching
|
||||
user's preferences.
|
||||
The information whether the video is live or not will also be returned.
|
||||
|
||||
:param str video_id: ID of the torrent linked with the video
|
||||
:param str instance: PeerTube instance hosting the video (optional)
|
||||
:return: URL of the video containing the resolution
|
||||
:rtype: str
|
||||
:return: a boolean indicating if the video is a live stream and the URL
|
||||
of the video (containing the resolution for non-live videos) as a
|
||||
string
|
||||
:rtype: tuple
|
||||
"""
|
||||
# Retrieve the information about the video including the different
|
||||
# resolutions available
|
||||
|
@ -218,16 +231,24 @@ class PeerTubeAddon():
|
|||
current_resolution = 0
|
||||
higher_resolution = -1
|
||||
url = ""
|
||||
is_live = False
|
||||
for video in video_files:
|
||||
# Get the resolution
|
||||
resolution = video["resolution"]
|
||||
resolution = video.get("resolution")
|
||||
if resolution is None:
|
||||
# If there is no resolution in the dict, then the video is a
|
||||
# live stream: no need to find the best resolution as there is
|
||||
# only 1 URL in this case
|
||||
url = video["url"]
|
||||
is_live = True
|
||||
return (is_live, url)
|
||||
if resolution == self.preferred_resolution:
|
||||
# Stop directly when we find the exact same resolution as the
|
||||
# user's preferred one
|
||||
kodi.debug("Found video with preferred resolution ({})"
|
||||
.format(self.preferred_resolution))
|
||||
url = video["url"]
|
||||
break
|
||||
return (is_live, url)
|
||||
elif (resolution < self.preferred_resolution
|
||||
and resolution > current_resolution):
|
||||
# Otherwise, try to find the best one just below the user's
|
||||
|
@ -255,7 +276,7 @@ class PeerTubeAddon():
|
|||
.format(higher_resolution))
|
||||
url = backup_url
|
||||
|
||||
return url
|
||||
return (is_live, url)
|
||||
|
||||
def _home_page(self):
|
||||
"""Display the items of the home page of the add-on"""
|
||||
|
@ -417,12 +438,18 @@ class PeerTubeAddon():
|
|||
elif action == "play_video":
|
||||
# This action comes with the id of the video to play as
|
||||
# parameter. The instance may also be in the parameters. Use
|
||||
# these parameters to retrieve the complete URL (containing the
|
||||
# resolution).
|
||||
url = self._get_video_url(instance=params.get("instance"),
|
||||
video_id=params.get("id"))
|
||||
# Play the video using the URL
|
||||
self._play_video(url)
|
||||
# these parameters to retrieve the complete URL of the video
|
||||
# (containing the resolution) and the type of the video (live
|
||||
# or not).
|
||||
is_live, url = self._get_video_url(
|
||||
instance=params.get("instance"),video_id=params.get("id"))
|
||||
|
||||
# Play the video (Kodi can play live videos (.m3u8) out of the
|
||||
# box whereas torrents must first be downloaded)
|
||||
if is_live:
|
||||
kodi.play(url)
|
||||
else:
|
||||
self._play_video(url)
|
||||
elif action == "select_instance":
|
||||
# Set the selected instance as the preferred instance
|
||||
self._select_instance(params["url"])
|
||||
|
@ -436,6 +463,6 @@ class PeerTubeAddon():
|
|||
kodi.open_dialog(
|
||||
title="Error: libtorrent could not be imported",
|
||||
message="You can still browse and search videos but you"
|
||||
" will not be able to play them.\n"
|
||||
"Please follow the instructions at {}"
|
||||
" will not be able to play them (except live"
|
||||
" videos).\nPlease follow the instructions at {}"
|
||||
.format(self.HELP_URL))
|
||||
|
|
|
@ -121,7 +121,8 @@ class PeerTube:
|
|||
"""Return the URLs of a video
|
||||
|
||||
PeerTube creates 1 URL for each resolution of a video so this method
|
||||
returns a list of URL/resolution pairs.
|
||||
returns a list of URL/resolution pairs. In the case of a live video,
|
||||
only an URL will be returned (no resolution).
|
||||
|
||||
:param str video_id: ID or UUID of the video
|
||||
:param str instance: URL of the instance hosting the video. The
|
||||
|
@ -134,21 +135,28 @@ class PeerTube:
|
|||
url="videos/{}".format(video_id),
|
||||
instance=instance)
|
||||
|
||||
# Depending if WebTorrent is enabled or not, the files corresponding to
|
||||
# different resolutions available for a video may be stored in "files"
|
||||
# or "streamingPlaylists[].files". Note that "files" will always exist
|
||||
# in the response but may be empty.
|
||||
if len(metadata["files"]) != 0:
|
||||
files = metadata["files"]
|
||||
else:
|
||||
files = metadata["streamingPlaylists"][0]["files"]
|
||||
|
||||
for file in files:
|
||||
if metadata["isLive"]:
|
||||
# When the video is a live, yield the unique playlist URL (there is
|
||||
# no resolution in this case)
|
||||
yield {
|
||||
"resolution": int(file["resolution"]["id"]),
|
||||
"url": file["torrentUrl"],
|
||||
"is_live": False
|
||||
"url": metadata['streamingPlaylists'][0]['playlistUrl'],
|
||||
}
|
||||
else:
|
||||
# For non live videos, the files corresponding to different
|
||||
# resolutions available for a video may be stored in "files" or
|
||||
# "streamingPlaylists[].files" depending if WebTorrent is enabled
|
||||
# or not. Note that "files" will always exist in the response but
|
||||
# may be empty so len() must be used.
|
||||
if len(metadata["files"]) != 0:
|
||||
files = metadata["files"]
|
||||
else:
|
||||
files = metadata["streamingPlaylists"][0]["files"]
|
||||
|
||||
for file in files:
|
||||
yield {
|
||||
"resolution": int(file["resolution"]["id"]),
|
||||
"url": file["torrentUrl"],
|
||||
}
|
||||
|
||||
def list_videos(self, start):
|
||||
"""List the videos in the instance
|
||||
|
|
Loading…
Reference in New Issue