mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-14 16:07:15 +00:00
Add voice activity analysis (#1466)
* Add hasVoiceActivity attribute to Media * Update tests for voice activity analysis * Fix movie year test * Add canAutoSync attribute to SubtitleStream
This commit is contained in:
parent
23ffc01756
commit
19582eb649
4 changed files with 20 additions and 1 deletions
|
@ -26,6 +26,7 @@ class Media(PlexObject):
|
||||||
height (int): The height of the media in pixels (ex: 256).
|
height (int): The height of the media in pixels (ex: 256).
|
||||||
id (int): The unique ID for this media on the server.
|
id (int): The unique ID for this media on the server.
|
||||||
has64bitOffsets (bool): True if video has 64 bit offsets.
|
has64bitOffsets (bool): True if video has 64 bit offsets.
|
||||||
|
hasVoiceActivity (bool): True if video has voice activity analyzed.
|
||||||
optimizedForStreaming (bool): True if video is optimized for streaming.
|
optimizedForStreaming (bool): True if video is optimized for streaming.
|
||||||
parts (List<:class:`~plexapi.media.MediaPart`>): List of media part objects.
|
parts (List<:class:`~plexapi.media.MediaPart`>): List of media part objects.
|
||||||
proxyType (int): Equals 42 for optimized versions.
|
proxyType (int): Equals 42 for optimized versions.
|
||||||
|
@ -61,6 +62,7 @@ class Media(PlexObject):
|
||||||
self.height = utils.cast(int, data.attrib.get('height'))
|
self.height = utils.cast(int, data.attrib.get('height'))
|
||||||
self.id = utils.cast(int, data.attrib.get('id'))
|
self.id = utils.cast(int, data.attrib.get('id'))
|
||||||
self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
|
self.has64bitOffsets = utils.cast(bool, data.attrib.get('has64bitOffsets'))
|
||||||
|
self.hasVoiceActivity = utils.cast(bool, data.attrib.get('hasVoiceActivity', '0'))
|
||||||
self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
|
self.optimizedForStreaming = utils.cast(bool, data.attrib.get('optimizedForStreaming'))
|
||||||
self.parts = self.findItems(data, MediaPart)
|
self.parts = self.findItems(data, MediaPart)
|
||||||
self.proxyType = utils.cast(int, data.attrib.get('proxyType'))
|
self.proxyType = utils.cast(int, data.attrib.get('proxyType'))
|
||||||
|
@ -441,6 +443,7 @@ class SubtitleStream(MediaPartStream):
|
||||||
Attributes:
|
Attributes:
|
||||||
TAG (str): 'Stream'
|
TAG (str): 'Stream'
|
||||||
STREAMTYPE (int): 3
|
STREAMTYPE (int): 3
|
||||||
|
canAutoSync (bool): True if the subtitle stream can be auto synced.
|
||||||
container (str): The container of the subtitle stream.
|
container (str): The container of the subtitle stream.
|
||||||
forced (bool): True if this is a forced subtitle.
|
forced (bool): True if this is a forced subtitle.
|
||||||
format (str): The format of the subtitle stream (ex: srt).
|
format (str): The format of the subtitle stream (ex: srt).
|
||||||
|
@ -459,6 +462,7 @@ class SubtitleStream(MediaPartStream):
|
||||||
def _loadData(self, data):
|
def _loadData(self, data):
|
||||||
""" Load attribute values from Plex XML response. """
|
""" Load attribute values from Plex XML response. """
|
||||||
super(SubtitleStream, self)._loadData(data)
|
super(SubtitleStream, self)._loadData(data)
|
||||||
|
self.canAutoSync = utils.cast(bool, data.attrib.get('canAutoSync'))
|
||||||
self.container = data.attrib.get('container')
|
self.container = data.attrib.get('container')
|
||||||
self.forced = utils.cast(bool, data.attrib.get('forced', '0'))
|
self.forced = utils.cast(bool, data.attrib.get('forced', '0'))
|
||||||
self.format = data.attrib.get('format')
|
self.format = data.attrib.get('format')
|
||||||
|
|
|
@ -447,6 +447,11 @@ class Movie(
|
||||||
""" Returns True if the movie has a credits marker. """
|
""" Returns True if the movie has a credits marker. """
|
||||||
return any(marker.type == 'credits' for marker in self.markers)
|
return any(marker.type == 'credits' for marker in self.markers)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hasVoiceActivity(self):
|
||||||
|
""" Returns True if any of the media has voice activity analyzed. """
|
||||||
|
return any(media.hasVoiceActivity for media in self.media)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hasPreviewThumbnails(self):
|
def hasPreviewThumbnails(self):
|
||||||
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
|
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
|
||||||
|
@ -1077,6 +1082,11 @@ class Episode(
|
||||||
""" Returns True if the episode has a credits marker. """
|
""" Returns True if the episode has a credits marker. """
|
||||||
return any(marker.type == 'credits' for marker in self.markers)
|
return any(marker.type == 'credits' for marker in self.markers)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hasVoiceActivity(self):
|
||||||
|
""" Returns True if any of the media has voice activity analyzed. """
|
||||||
|
return any(media.hasVoiceActivity for media in self.media)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hasPreviewThumbnails(self):
|
def hasPreviewThumbnails(self):
|
||||||
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
|
""" Returns True if any of the media parts has generated preview (BIF) thumbnails. """
|
||||||
|
|
|
@ -77,6 +77,7 @@ def test_video_Movie_attrs(movies):
|
||||||
assert "Animation" in [i.tag for i in movie.genres]
|
assert "Animation" in [i.tag for i in movie.genres]
|
||||||
assert "imdb://tt1172203" in [i.id for i in movie.guids]
|
assert "imdb://tt1172203" in [i.id for i in movie.guids]
|
||||||
assert movie.guid == "plex://movie/5d776846880197001ec967c6"
|
assert movie.guid == "plex://movie/5d776846880197001ec967c6"
|
||||||
|
assert movie.hasVoiceActivity is False
|
||||||
assert movie.hasPreviewThumbnails is False
|
assert movie.hasPreviewThumbnails is False
|
||||||
assert utils.is_metadata(movie._initpath)
|
assert utils.is_metadata(movie._initpath)
|
||||||
assert utils.is_metadata(movie.key)
|
assert utils.is_metadata(movie.key)
|
||||||
|
@ -108,7 +109,7 @@ def test_video_Movie_attrs(movies):
|
||||||
assert movie.userRating is None
|
assert movie.userRating is None
|
||||||
assert movie.viewCount == 0
|
assert movie.viewCount == 0
|
||||||
assert utils.is_int(movie.viewOffset, gte=0)
|
assert utils.is_int(movie.viewOffset, gte=0)
|
||||||
assert movie.year == 2009
|
assert movie.year >= 2008
|
||||||
# Audio
|
# Audio
|
||||||
audio = movie.media[0].parts[0].audioStreams()[0]
|
audio = movie.media[0].parts[0].audioStreams()[0]
|
||||||
if audio.audioChannelLayout:
|
if audio.audioChannelLayout:
|
||||||
|
@ -150,6 +151,7 @@ def test_video_Movie_attrs(movies):
|
||||||
assert utils.is_int(media.id)
|
assert utils.is_int(media.id)
|
||||||
assert utils.is_metadata(media._initpath)
|
assert utils.is_metadata(media._initpath)
|
||||||
assert media.has64bitOffsets is False
|
assert media.has64bitOffsets is False
|
||||||
|
assert media.hasVoiceActivity is False
|
||||||
assert media.optimizedForStreaming in [None, False, True]
|
assert media.optimizedForStreaming in [None, False, True]
|
||||||
assert media.proxyType is None
|
assert media.proxyType is None
|
||||||
assert media._server._baseurl == utils.SERVER_BASEURL
|
assert media._server._baseurl == utils.SERVER_BASEURL
|
||||||
|
@ -1223,6 +1225,7 @@ def test_video_Episode_attrs(episode):
|
||||||
assert episode.grandparentTitle == "Game of Thrones"
|
assert episode.grandparentTitle == "Game of Thrones"
|
||||||
assert episode.guid == "plex://episode/5d9c1275e98e47001eb84029"
|
assert episode.guid == "plex://episode/5d9c1275e98e47001eb84029"
|
||||||
assert "tvdb://3254641" in [i.id for i in episode.guids]
|
assert "tvdb://3254641" in [i.id for i in episode.guids]
|
||||||
|
assert episode.hasVoiceActivity is False
|
||||||
assert episode.hasPreviewThumbnails is False
|
assert episode.hasPreviewThumbnails is False
|
||||||
assert episode.index == 1
|
assert episode.index == 1
|
||||||
assert episode.episodeNumber == episode.index
|
assert episode.episodeNumber == episode.index
|
||||||
|
@ -1279,6 +1282,7 @@ def test_video_Episode_attrs(episode):
|
||||||
assert media.container in utils.CONTAINERS
|
assert media.container in utils.CONTAINERS
|
||||||
assert utils.is_int(media.duration, gte=150000)
|
assert utils.is_int(media.duration, gte=150000)
|
||||||
assert utils.is_int(media.height, gte=200)
|
assert utils.is_int(media.height, gte=200)
|
||||||
|
assert media.hasVoiceActivity is False
|
||||||
assert utils.is_int(media.id)
|
assert utils.is_int(media.id)
|
||||||
assert utils.is_metadata(media._initpath)
|
assert utils.is_metadata(media._initpath)
|
||||||
if media.optimizedForStreaming:
|
if media.optimizedForStreaming:
|
||||||
|
|
|
@ -504,6 +504,7 @@ if __name__ == "__main__": # noqa: C901
|
||||||
if not opts.unclaimed and account and account.subscriptionActive:
|
if not opts.unclaimed and account and account.subscriptionActive:
|
||||||
server.settings.get("GenerateIntroMarkerBehavior").set("never")
|
server.settings.get("GenerateIntroMarkerBehavior").set("never")
|
||||||
server.settings.get("GenerateCreditsMarkerBehavior").set("never")
|
server.settings.get("GenerateCreditsMarkerBehavior").set("never")
|
||||||
|
server.settings.get("GenerateVADBehavior").set("never")
|
||||||
server.settings.get("MusicAnalysisBehavior").set("never")
|
server.settings.get("MusicAnalysisBehavior").set("never")
|
||||||
server.settings.get("GenerateBIFBehavior").set("never")
|
server.settings.get("GenerateBIFBehavior").set("never")
|
||||||
server.settings.get("GenerateChapterThumbBehavior").set("never")
|
server.settings.get("GenerateChapterThumbBehavior").set("never")
|
||||||
|
|
Loading…
Reference in a new issue