kjtsune / embyToLocalPlayer

etlp - Emby/Jellyfin 调用外部本地播放器,并回传播放记录。适配 Plex。
564 stars 38 forks source link

Miss duration in plex media tv show! #64

Closed zhengsun2020 closed 2 weeks ago

zhengsun2020 commented 1 month ago

when i saw tv show ,i got this info from cmd out:

File "D:\Downloads\embyToLocalPlayer-python-embed-win32\utils\http_server.py", line 65, in do_POST data = parse_received_data_emby(data) if self.path.startswith('/emby') else parse_received_data_plex(data) File "D:\Downloads\embyToLocalPlayer-python-embed-win32\utils\tools.py", line 489, in parse_received_data_plex duration = data['duration'] KeyError: 'duration'

i print data from Plex and tv show send info json includ “duration” in selected season espoid 'Media': [{ 'id': 586519, 'duration': 1445162, 'bitrate': 3018, 'width': 1920, 'height': 1080,

but no in next espoid 'Media': [{ 'id': 586520, 'Part': [{ 'id': 608139, 'key': '/library/parts/608139/1722653858/file.mkv', 'file': 'D:\XXXXXXX', 'size': 435248006 }] so the program process this json can not get duration, and "KeyError: 'duration'" here

And the last year tv shows added in my lib , PLEX would send all duration of every espoid!

Finallly I modified these line in tools.py , it work fine:

    duration = data.get('duration')

    if data['Part'][0].get('Stream'):
        sub_dict_list = [i for i in data['Part'][0]['Stream'] if i.get('streamType') == 3 and i.get('key')]
kjtsune commented 1 month ago

docker pull linuxserver/plex 版本1.40.4.8679 最新版无法复现,什么服务端版本,注意不是 webui 版本。

zhengsun2020 commented 1 month ago

版本1.40.4.8679 服务器 VPS海外 和 国内的Windows都能复现,我已经修改我自己的代码了。主要是 获得服务器传回的jason 很奇怪 电视剧有些集没有时长信息等详细信息,看过一次会有,因为脚本要读取所有集信息,有的就是没有。不知道是否和plex的TV刮削出问题有关系。

注释了 #duration = data['duration'] 并做了如下两处修改 if data['Part'][0].get('Stream') is not None: sub_dict_list = [i for i in data['Part'][0]['Stream'] if i.get('streamType') == 3 and i.get('key')] else: sub_dict_list = [] 和

    duration = meta.get('duration')  
    if duration is not None:  
        total_sec = int(duration) // (10 ** 3)  
    else:  
        duration = "60000000"
        total_sec = 60000  # 或者其他合适的默认值
    position = start_sec / total_sec
kjtsune commented 1 month ago

新入库的电视项目,没点开详情或者播放过的,浏览器进入下一集详情会看不到字幕视频流等数据,同时也会无法快速播放。体现在本地服浏览器播放,点下一集无法秒播,要转很久。用本项目调用播放的话,下一集会卡住。等plex自己修了。

zhengsun2020 commented 1 month ago

是的 就是因为他不传送下一集的各种信息,而咱们的脚本 有的地方不是 get方法,是直接引用,这里就报错了,我就把这几个地方增加了判断。

zhengsun2020 commented 1 month ago

我怀疑他们就打算这么做下去了,我的1.40 还降级不了 1.32

zhengsun2020 commented 1 month ago

新入库的电视项目,没点开详情或者播放过的,浏览器进入下一集详情会看不到字幕视频流等数据,同时也会无法快速播放。体现在本地服浏览器播放,点下一集无法秒播,要转很久。用本项目调用播放的话,下一集会卡住。等plex自己修了。

而且刮削的剧情介绍也没有,必须手工刷新元数据

kjtsune commented 1 month ago

是的 就是因为他不传送下一集的各种信息,而咱们的脚本 有的地方不是 get方法,是直接引用,这里就报错了,我就把这几个地方增加了判断。

不止不传送,而是没有去获取,不然就不会播放下一集卡住了。 这几个数据都有作用,目前不考虑适配,建议降级服务端。

对于想使用的用户,可以自行修改以下几个变量的值,外挂字幕和部分功能可能会失效。 https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L489 duration = data.get('duration', 10**12)

https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L494 sub_dict_list = []

https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L522 total_sec = duration // (10 ** 3)

zhengsun2020 commented 1 month ago

是的 就是因为他不传送下一集的各种信息,而咱们的脚本 有的地方不是 get方法,是直接引用,这里就报错了,我就把这几个地方增加了判断。

不止不传送,而是没有去获取,不然就不会播放下一集卡住了。 这几个数据都有作用,目前不考虑适配,建议降级服务端。

对于想使用的用户,可以自行修改以下几个变量的值,外挂字幕和部分功能可能会失效。

https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L489

duration = data.get('duration', 10**12) https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L494

sub_dict_list = [] https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/utils/tools.py#L522

total_sec = duration // (10 ** 3)

降级我试过 告诉我系统DB失败启动不了

kjtsune commented 1 month ago

那就先这样子用吧。 本地挂载用户可以启用读盘模式来解决外挂字幕问题。

zhengsun2020 commented 1 month ago

请问一下读盘模式是啥,我从来没开过,我看的都是GD网盘的资源。可能外挂字幕也少

zhengsun2020 commented 1 month ago

明白了,我测试了读盘模式可以,那我平常一直开着读盘模式可以吗?有什么缺点?

kjtsune commented 1 month ago

https://github.com/kjtsune/embyToLocalPlayer/blob/7be8a192484af4f4e078332126959addde1d018e/README.md#L116-L119

kjtsune commented 1 month ago

明白了,我测试了读盘模式可以,那我平常一直开着读盘模式可以吗?有什么缺点?

可以,缺点不知道。

zhengsun2020 commented 1 month ago

我看日志明白了,本地模式必须服务器和文件以及播放是在本地才行,如果是远端服务器开着本地模式,这时本地没有实际文件那就是报错

zhengsun2020 commented 1 month ago

这个1.40改动太大了,而且我测试了 无法回退1.32.8 简直无语了 ,最近刮削也完蛋

kjtsune commented 1 month ago

我看日志明白了,本地模式必须服务器和文件以及播放是在本地才行,如果是远端服务器开着本地模式,这时本地没有实际文件那就是报错

远端服务器也可以,本地挂载GD就可以。看 ini 配置文件。

kjtsune commented 1 month ago

这个1.40改动太大了,而且我测试了 无法回退1.32.8 简直无语了 ,最近刮削也完蛋

跨大版本回退一般需要重建。刮削是因为被墙了。

zhengsun2020 commented 1 month ago

重建就算了,而且我发现 现在的plex 外置srt 出不来是因为 download=0不起作用,服务器还是会按照下载处理,所以potplayer就无法支持srt,Emby就是直接可以访问的方式打开srt。 这个我调试了半天也不行只能本地硬盘模式就能解决,但是得自己想着点切换,因为有的时候需要连接朋友的plex就不能用本地硬盘模式了。而且朋友的服务器共享的就可以按照 download=0处理,只有我自己的账户的服务器不行

kjtsune commented 1 month ago

只能本地硬盘模式就能解决,但是得自己想着点切换

# 当服务端路径包含以下前缀强制使用读盘模式,忽略油猴设置。逗号隔开,例如: /disk/p, disk/e force_disk_mode_path = 临时曲线救国方案。

kjtsune commented 1 month ago

plex 外置srt 出不来是因为 download=0不起作用

mpv 没这问题,pot 原因未知。 随便修了 plex 选中字幕时的bug。

zhengsun2020 commented 1 month ago

[08/12/24 22:30:51.7] ['C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe', 'http://127._mix_host_:32400/library/parts/598744/1716962577/file.mkv?download=0&X-Plex-Token=_hide_api_key_', '/sub=http://127._mix_host_:32400/library/streams/2241525?download=0&X-Plex-Token=_hide_api_key_', '/seek=00:00:00', '/title=国庆节 | 摩登家庭 - S10E01 - 第 1 集.mkv'] [08/12/24 22:30:51.7] send 1 requests to check subtitles [08/12/24 22:30:52.7] disable playlist cuz is_http_sub [08/12/24 22:31:12.9] update progress: 摩登家庭 - S10E01 - 第 1 集.mkv stop_sec=13

http://127._mix_host_:32400/library/streams/2241525?download=0&X-Plex-Token=_hide_api_key_ 换成我的IP和Token 。Plex的URL访问会下载srt文件,而EMBY的URL就是直接浏览器中显示srt的内容。就这么点区别。这个应该是和服务器有关系。

kjtsune commented 1 month ago

https://192-168-123-123.abcdefg.plex.direct:32400/library/streams/13350?download=0&X-Plex-Token=_hide_api_key_

可以用局域网ip 192.168.... 访问plex播放试试看。 我测试也是直接浏览器中显示srt的内容,但链接格式和你有点区别。这种是他自己转换的。

zhengsun2020 commented 1 month ago

是的我就是这么测试的,我的1.40.4.8679服务端(Windows、linux)都有这个问题,就是一输入url这种(URL换成了局域网IP)然后就是下载过来了,而不是显示在浏览器中。这个应该是服务器的问题感觉是

kjtsune commented 1 month ago

那就不懂了,我也是这个版本。版本1.40.4.8679

zhengsun2020 commented 1 month ago

我再找找服务设置问题吧

kjtsune commented 1 month ago

当然,只是会在浏览器里显示而已,我的pot也是无法加载字幕的。mpv可以。

zhengsun2020 commented 1 month ago

外置srt 您那里也不行是吧,那就不一定是和这个有关。那就算了 我用mpv也可

kjtsune commented 1 month ago

是的。

我还尝试下载到本地后指定路径,也是不行,不管他了。 https://github.com/kjtsune/embyToLocalPlayer/blob/be0b62b228a0404f90cf35fc6b8f830344a25cf8/utils/players.py#L761-L763

    if sub_file:
        if 'Plex-Token' in sub_file:
            sub_file = save_sub_file(sub_file)
zhengsun2020 commented 1 month ago

本地模式是因为他自己去取 同名的srt 可以显示。但是如果直接指定另一个目录下的 srt文件(就是先下载字幕然后播放) 比如 "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" "http://127.0.0.1:32400/library/parts/598744/1716962577/file.mkv?download=0&X-Plex-Token=ScUthCDZ8-h-ui7Eyn-K" /sub="D:\home\摩登家庭 - S10E01 - 第 1 集.srt" /seek=00:18:33 /title="国庆节 | 摩登家庭 - S10E01 - 第 1 集.mkv" 这样是可以的,然后我修改了您对应文件的代码,确实无法工作

但是我测试了 "C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe" "http://127.0.0.1:32400/library/parts/598744/1716962577/file.mkv?download=0&X-Plex-Token=ScUthCDZ8-h-ui7Eyn-K" /sub="D:\Downloads\embyToLocalPlayer-python-embed-win32.tmp\tmp_sub.srt" /seek=00:18:33 /title="国庆节 | 摩登家庭 - S10E01 - 第 1 集.mkv" 以上我在cmd中启动加载已经都正常了

然后我增加代码中 " 符号 代码生成的是 [08/13/24 12:27:45.2] ['C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe', 'http://127._mix_host_:32400/library/parts/598744/1716962577/file.mkv?download=0&X-Plex-Token=_hide_api_key_', '/sub="D:\Downloads\embyToLocalPlayer-python-embed-win32\.tmp\tmp_sub.srt"', '/seek=00:00:00', '/title=国庆节 | 摩登家庭 - S10E01 - 第 1 集.mkv']

还是加载不了字幕。。。。

zhengsun2020 commented 1 month ago

如下修改就好了

if sub_file:
    if 'Plex-Token' in sub_file:
        sub_file = save_sub_file(sub_file)
        newsub_file = sub_file.replace('_', ' ')
        if os.path.exists(newsub_file):
            os.remove(newsub_file)
        os.rename(sub_file, newsub_file)
        sub_file = newsub_file
    cmd.append(f'/sub={sub_file}')
kjtsune commented 4 weeks ago

这都被你试出来了,厉害。更新了。 https://github.com/kjtsune/embyToLocalPlayer/blob/4f58f3c09773fe5595a343b6d5b9a6fd0679bc56/utils/players.py#L763-L764

zhengsun2020 commented 4 weeks ago

其实调试了一下,发现这个subprocess.Popen执行不给字幕文件名自动加"" 所以POT不认,如果代码加 "" 自动就转成了 \" POT也不认,所以弄一个空格他就自动加 " 其实安装目录名弄一个空格也可以就不用改这个代码,但用的人万一不知道呢 ;) 这种调试工作老程序出身不难只不过不熟悉Python,也是最近才用上项目才看的。

另外说一下:我的Plex服务器有的时候不能传送所有电视剧的信息过来,原因可能是我个人原因刮削刮得strm文件然后替换真文件,如果第一次进剧集没来得及扫实际文件内容就播放,这时程序不提前判断就会异常(因为时长等流信息都没有,但不影响看当前集),所以我修改了一下,如果别人没有这个现象就不用合并主线:

for _index, meta in enumerate(metas): res = base_info_dict.copy() data = meta['Media'][0] item_id = data['id']

注释掉这行后面再取

    #duration = data['duration']
    file_path = data['Part'][0]['file']
    size = data['Part'][0]['size']
    stream_path = data['Part'][0]['key']
    stream_url = f'{scheme}://{netloc}{stream_path}?download=0&X-Plex-Token={api_key}'

字幕如果没取到就设置为[]先播放

    if data['Part'][0].get('Stream') is not None:
        sub_dict_list = [i for i in data['Part'][0]['Stream'] if i.get('streamType') == 3 and i.get('key')]
    else:
        sub_dict_list = []

    sub_selected = None
    sub_key = None
    if _index == 0:
        if sub_selected := [i for i in sub_dict_list if i.get('selected')]:
            #sub_key = sub_selected
            sub_key = sub_selected[0].get('key')

    if (_index == 0 and not sub_selected) or _index != 0:
        for _sub in sub_dict_list:
            _sub['order'] = configs.check_str_match(
                (_sub.get('title', '') + ',' + _sub['displayTitle']).lower(),
                'dev', 'subtitle_priority', log=False, order_only=True)
        sub_dict_list = [i for i in sub_dict_list if i['order'] != 0]
        sub_dict = sub_dict_list[0] if sub_dict_list else {}
        sub_key = sub_dict.get('key')
    #print("T3:")
    #print(sub_key)            
    sub_file = f'{scheme}://{netloc}{sub_key}?download=0&X-Plex-Token={api_key}' \
        if not mount_disk_mode and sub_key else None
    media_path = translate_path_by_ini(file_path) if mount_disk_mode else stream_url
    basename = os.path.basename(file_path)
    media_basename = os.path.basename(media_path)
    title = meta.get('title', basename)
    media_title = title if title == basename else f'{title} | {basename}'

    seek = meta.get('viewOffset')
    rating_key = meta['ratingKey']
    start_sec = int(seek) // (10 ** 3) if seek and not query.get('extrasPrefixCount') else 0

    fake_name = os.path.splitdrive(file_path)[1].replace('/', '__').replace('\\', '__')

如果确实没有取到则设置一个够大的时间先播放

    duration = meta.get('duration')  
    if duration is not None:  
        total_sec = int(duration) // (10 ** 3)  
    else:  
        duration = "60000000"
        total_sec = 60000  # 或者其他合适的默认值
    position = start_sec / total_sec
kjtsune commented 4 weeks ago

我就是本地文件的,没有网盘,也是会缺失数据。 不过这次又测试,跳下一集播放不会卡住了。

简单更新了下。也给用户提示会有字幕等问题。

zhengsun2020 commented 4 weeks ago

只要读过一次文件就OK了,我是本地的 strm文件改名为 mkv 然后扫库,实际没有媒体数据,然后再挂网盘的实际媒体文件。所以第一次播放的时候后面的集和当前集都没有媒体数据。程序如果不判断直接取就会异常。所以我改了几个地方就是适应这种情况

kjtsune commented 2 weeks ago

https://github.com/kjtsune/embyToLocalPlayer/commit/01b188d58531a30c96a788e8d6dc6f5951435e66