MoviePilot-Plugins icon indicating copy to clipboard operation
MoviePilot-Plugins copied to clipboard

BGM打格子错误

Open l429609201 opened this issue 7 months ago • 27 comments

如下图所示,我在播放RE0:从零开始的异世界生活 第三季 第一集 的时候打格子插件识别成了RE0第一季

Image

个人想法,不知道可否用作参考: 1、在tmdbid等查询不到的时候,根据季和集号(以上述RE0为例 通常为Seasons组 ) 找到对应是那一集,在根据集的日文名称查找BGM对应需要打格子的那一集,在进行打格子? 2、根据剧集组前几季的集数,对实际需要打格子的集数做一个偏移操作,以BGM中RE0的第三季为例,BGM中集数完全按照官方网站的集数来的,而实际剧集组的集数为S03E01,在BGM中实际要打的为S03E51,这个51=第一季集数+第二季集数+01,是否可以根据这个关系做一个打格子的关联?

l429609201 avatar May 12 '25 13:05 l429609201

@happyTonakai 这个dalao在负责这个插件

honue avatar May 12 '25 15:05 honue

第一种方法我看看bgm的API能否通过单集名来查询,不过我不清楚是否所有单集都有自己独立的标题?

第二种方法可能不太行,因为在bgm自己的命名里,有的番剧第二季是以上一季结尾+1集开始,有的是以第1集开始。

我觉得另一种可行且稳健的方案是直接让用户自定义剧集映射和偏移,像无职这种单季还分上下部分的,这种方式是最合适的,比如: 无职转生~到了异世界就拿出真本事~S01E12->无职转生~到了异世界就拿出真本事~ 第2部分E12 无职转生~到了异世界就拿出真本事~S02E01->无职转生Ⅱ ~到了异世界就拿出真本事~E01

就像mp本体也提供了类似的自定义映射用于刮削,不知道大家对这种方式的接受程度如何

happyTonakai avatar May 12 '25 15:05 happyTonakai

我觉得针对使用剧集组后的打格子确定季和集的重点还是要放在TMDB上面,像你说的有些番剧第二季从上一季最后一集+1集开始的,有的番剧是从第一集开始这个问题,这主要是取决于制作方的定义,最近的例子就是 从零开始的异世界生活无职转生,如果是按照制片方的顺序排序的,打格子插件应该是可以正常打的,出问题的地方是使用了TMDB剧集组的番剧,无法正确打格子。

要解决的问题还是开头说的,如何确定剧集组的集号与BGM上的集号的逻辑关系,这样才能正确的打格子

l429609201 avatar May 12 '25 16:05 l429609201

根据单集日文名来判断bgm的逻辑我写好了,我先测试几天。不过我看了一下你的问题并不在这。

tmdb上Re0只有一季,第三季第一集应该是S01E51,但是你这里日志是S03E01。因此tmdb api返回的是2016年第一季第一集。

你需要保证刮削的信息和tmdb一致,不然在播放客户端显示的刮削信息也不对啊。

即便能够根据单集日文名来判断,但是前提是季的识别没有问题,这个提交只能解决tmdb和bgm的起始集有偏移的情况。

happyTonakai avatar May 13 '25 04:05 happyTonakai

实际上,二者是都是正确的,因为我是按照TMDB的剧集组进行刮削的,TMDB有查询剧集组的API

Image

l429609201 avatar May 13 '25 04:05 l429609201

查到之后要怎么用呢,API返回结果是这样的:

{
  "results": [
    {
      "description": "",
      "episode_count": 0,
      "group_count": 1,
      "id": "6735f2b8ffe3878e9e9f8e9a",
      "name": "BD order",
      "network": null,
      "type": 3
    },
    {
      "description": "",
      "episode_count": 128,
      "group_count": 4,
      "id": "641eb9d6b234b9007ac67063",
      "name": "Seasons",
      "network": null,
      "type": 6
    },
    {
      "description": "",
      "episode_count": 25,
      "group_count": 1,
      "id": "6717c7da88be821f649a8fc2",
      "name": "Season 2",
      "network": null,
      "type": 7
    },
    {
      "description": "",
      "episode_count": 16,
      "group_count": 1,
      "id": "6717c9fc50a6eb0bfbc28ae6",
      "name": "Season 3",
      "network": null,
      "type": 7
    }
  ],
  "id": 65942
}

第一季25集,在返回结果中没有包含,而且这些group的id获取到之后好像没有进一步检索的api了

直接使用这个api查询第三季查不到结果:https://api.tmdb.org/3/tv/{tmdbid}/season/{season_num}?language={original_language}&api_key={self._tmdb_key}

        def get_tv_season_detail(tmdbid, season) -> List[dict]:
            seasons = [season, 1]
            for (
                season_num
            ) in seasons:  # Use season_num to avoid shadowing the outer season variable
                url = f"https://api.tmdb.org/3/tv/{tmdbid}/season/{season_num}?language={original_language}&api_key={self._tmdb_key}"
                resp = self._request.get(url).json()  # Using self._request
                if resp and resp.get("success") is False:
                    continue
                return resp
            return None  # Return None if no season detail is found

在这里实际上是给了一个第一季的保底 seasons = [seasons, 1],似乎不应该给这个保底,否则可能会打错,你日志中第三季打到第一季就是因为这个

happyTonakai avatar May 13 '25 05:05 happyTonakai

https://developer.themoviedb.org/reference/tv-episode-group-details

找到了,我试一下,当用season找不到的话,改用episode group查询

happyTonakai avatar May 13 '25 05:05 happyTonakai

对,我实际上想说的就是这个,用组的id去查详细信息,然后根据这个详细信息去做一个bgm的匹配,比如说集名称的匹配,现在越来越多的番剧开始有第二季,根据TMDB的规则,肯定会有更多的剧集组的

l429609201 avatar May 13 '25 05:05 l429609201

还有个问题需要和你确认,你是怎么刮削的,这是 https://developer.themoviedb.org/reference/tv-episode-group-details 给出的结果,可以看到他即便是第三季,也是以E51开始的,而你这里是E01,导致无法匹配到集数

  "episodes": [
        {
          "air_date": "2024-10-02",
          "episode_number": 51,
          "episode_type": "standard",
          "id": 5524784,
          "name": "Theatrical Malice",
          "overview": "A year has passed since the battle at the Sanctuary, and Subaru has been spending fulfilling days united with Emilia's camp. However, his peaceful everyday life ends with the arrival of a single letter.",
          "production_code": "",
          "runtime": 91,
          "season_number": 1,
          "show_id": 65942,
          "still_path": "/iu7ErnYe1zYGn8T1cGoGgGtCyj9.jpg",
          "vote_average": 8.4,
          "vote_count": 7,
          "order": 0
        },
        {
          "air_date": "2024-10-09",
          "episode_number": 52,
          "episode_type": "standard",
          "id": 5563240,
          "name": "A Showdown of Fire and Ice",
          "overview": "Subaru desperately tries to fend off the attack from Sin Archbishop Sirius. But then, other Archbishops appear...",
          "production_code": "",
          "runtime": 23,
          "season_number": 1,
          "show_id": 65942,
          "still_path": "/jhu9DiB5fFgJmlj4BTj74MV9bUQ.jpg",
          "vote_average": 9.2,
          "vote_count": 6,
          "order": 1
        },

一个不稳妥的办法是先用episode_number匹配,无法匹配的时候使用order+1,现在在同步bgm的逻辑里也有类似的操作

happyTonakai avatar May 13 '25 05:05 happyTonakai

使用剧集组刮削的组,通常是使用 Seasons组,这个组是包含了所有季度的,其他的番剧的Seasons组也是如此,所以你检索的时候选择的组要是名称为Seasons的组,使用这个组是对应的编号是可以加上前几季的总集数来匹配的,以这部在讨论的番剧为例,我再看的是S03E01,那么加上第一季集数25和第二季集数25的可以得到BGM对应的集S03E51

编辑回复 我才注意API返回的和我们实际的想的不太一样,是可以根据你说的这个方法来同步,这个API返回的含有了绝对数字episode_number=51,可以直接通过这个来进行匹配BGM

l429609201 avatar May 13 '25 05:05 l429609201

OK,确实应该通过seasons来确定,里面包含了所有季,不过依然是刚才的问题,这个api返回的第三季第一集是episode51,但是你在emby中的文件名是S03E01,他能够正确识别,我想确认一下如果是S03E51能否正确识别,如果不能的话我就优先匹配 order + 1,否则两者都需要顺序匹配

tmdb的episode number不一定和bgm的集数是对应的吧,bgm的第二季第一季也不一定是接着上一季的集数命名的,最能够匹配的就是你说的原始日文的标题

还有个问题,我发现有的剧集不包含seasons字段,比如clannad,只能说试着去匹配吧。。

{
  "results": [
    {
      "description": "",
      "episode_count": 25,
      "group_count": 1,
      "id": "5de8c6bda313b80012935f55",
      "name": "Clannad After Story (Netflix)",
      "network": {
        "id": 213,
        "logo_path": "/wwemzKWzjKYJFfCeiB57q3r4Bcm.png",
        "name": "Netflix",
        "origin_country": ""
      },
      "type": 4
    },
    {
      "description": "",
      "episode_count": 24,
      "group_count": 2,
      "id": "5de8c6127646fd00139b883d",
      "name": "Clannad (Netflix)",
      "network": {
        "id": 213,
        "logo_path": "/wwemzKWzjKYJFfCeiB57q3r4Bcm.png",
        "name": "Netflix",
        "origin_country": ""
      },
      "type": 4
    }
  ],
  "id": 24835
}

happyTonakai avatar May 13 '25 06:05 happyTonakai

1、这个要分情况的,因为不是所有番剧都有剧集组,正常分季的番剧可以按照原有逻辑进行匹配以及打格子,比如clannad,在TMDBBGM都是正常分季的,这种就可以按照原有逻辑正常打格子。 2、针对1的情况下无法打格子的可以按照我们讨论的处理,进行剧集组匹配判断,也是有你说的两种情况(如果是S03E51能否正确识别,如果不能的话我就优先匹配 order + 1,否则两者都需要顺序匹配)ps:据我所知S03E51的这类情况比较少,我知道的就只有海贼王是这样的,现在TMDB的MOD都是直接粗鲁的全部塞到一起,比如这两部 我心里危险的东西香格里拉边境

l429609201 avatar May 13 '25 06:05 l429609201

要合并的话a我哈 @happyTonakai

honue avatar May 13 '25 12:05 honue

嗯,还有点问题,我有空再调试一下

happyTonakai avatar May 13 '25 12:05 happyTonakai

@l429609201 可以帮忙测试一下,用“插件重装重载”插件从我的分支安装一下,我这个季度没追啥续作,覆盖不全面

happyTonakai avatar May 13 '25 13:05 happyTonakai

好。版本号没改,但是代码改动了是吧?

l429609201 avatar May 13 '25 13:05 l429609201

重载之后是1.9.0,初始化后在日志中会打印版本号

happyTonakai avatar May 13 '25 13:05 happyTonakai

我测试的时候发现了1个问题,

Image

我看了代码,你对季和集的提取,似乎有一些问题

season_id, episode_id = map(int, [event_info.season_id, event_info.episode_id])

emby的webhook中你直接取season_id和episode_id是有可能取不到对应的,我在播放从零开始的异世界生活的第三季第一集的时候是可以获取的,但是播放香格里拉边境和我心里危险的东西时就读取不到,出现上图中的报错 实际上webhook中是有季和集的

'Item': { 'Name': '病例.13「我们在寻找」', 'ServerId': '09d87215996b4f62bf8d3df6fc271c1e', 'Id': '70771', 'DateCreated': '2024-11-19T15: 29: 25.0000000Z', 'PresentationUniqueKey': '422981-zh-CN-b3394d19e4374c3ca3bb8069874e08e8-002-0001', 'Container': 'mp4', 'PremiereDate': '2024-01-06T16: 00: 00.0000000Z', 'ExternalUrls': [ { 'Name': 'IMDb', 'Url': 'https: //www.imdb.com/title/tt28103734' }, { 'Name': 'TheTVDB', 'Url': 'https: //thetvdb.com/?tab=episode&id=9852692' }, { 'Name': 'Trakt', 'Url': 'https: //trakt.tv/search/tmdb/None?id_type=episode' } ], 'Path': '/data/动漫/我心里危险的东西/Season2/我心里危险的东西-S02E01.mp4', 'Overview': '手臂骨折的市川,开始了他有些不便的第三学期生活。班主任向市川提议可以请跟他交情较好的山田来帮助》> 他,但市川以“跟她交情并没有很好”为由而拒绝。好死不死,这段对话被山田听见了……市川为此备感焦急,但另一方面, 山田> 却拜托同班同学足立去协助市川。再度认知到她的温柔的市川,对山田说出一些些内心压抑已久的话……', 'Taglines': [ ], 'Genres': [ ], 'CommunityRating': 7.9, 'RunTimeTicks': 13844266670, 'Size': 270052571, 'FileName': '我心里危险的东西-S02E01.mp4', 'Bitrate': 1560516, 'ProductionYear': 2024, 'IndexNumber': 1, <=第几集在这 'ParentIndexNumber': 2, <= 第几季在这 'ProviderIds': { 'Tmdb': 'None', 'Tvdb': '9852692', 'IMDB': 'tt28103734' }

-- 编辑一个补充说明 emby原始的webhook返回时没有season_id和episode_id的,我在mp的debug日志中看了

l429609201 avatar May 13 '25 14:05 l429609201

https://github.com/jxxghp/MoviePilot/blob/bcbfe2ccd5d39b177f3038f54e47a6af88359fec/app/modules/emby/emby.py#L987-L988

mp中就是这么实现的,读取ParentIndexNumber和IndexNumber

happyTonakai avatar May 14 '25 08:05 happyTonakai

可能还是出在你的刮削是以episode group为基础的原因?要解决这个问题,可以在mp传过来None的时候,使用正则对item_name进行匹配,反正上面刚好对title做匹配的时候用到了S\d+E\d+

                match = re.match(r"^(.+)\sS\d+E\d+\s.+", event_info.item_name)
                if match:
                    title = match.group(1)
                else:
                    title = event_info.item_name.split(' ')[0]

                # 季 集
                season_id, episode_id = map(int, [event_info.season_id, event_info.episode_id])

happyTonakai avatar May 14 '25 08:05 happyTonakai

应该是title的问题,但是奇怪的一点在于,我播放RE0的时候是可以的,但是其他的都报错,我正在尝试解决。。

RE0的

event = 'playback.pause' channel = 'emby' server_name = 'emby' item_type = 'TV' item_name = 'Re:从零开始的异世界生活 S3E16 水门都市攻防战结果' item_id = '62293' item_path = '/data/动漫/Re:从零开始的异世界生活/Season 3/Re:从零开始的异世界生活 - S03E16.mkv' season_id = 3 episode_id = 16 tmdb_id = None overview = '奥托险些被莱伊吞噬,千钧一发之际,被碧翠丝所救。对着用以前吃过的“记忆”编织蕾姆的话来嘲讽的莱伊,碧翠丝和奥拓发誓只有这家伙绝不能和昴见面。但是,没有昴的碧翠丝仅能使用剩余5次魔法。她击碎魔晶石,接连...' percentage = 0.05481309562533306 ip = '192.168.10.254' device_name = 'Railgun-m-PC' client = 'Emby Theater' user_name = 'root_nas' image_url = 'https://image.tmdb.org/t/p/original/ai8bVS8Suvu4ErBhmgBvtESirBY.jpg' item_favorite = None save_reason = None item_isvirtual = None media_type = 'Episode'

我心危的

event = 'playback.pause' channel = 'emby' server_name = 'emby' item_type = 'TV' item_name = '我心里危险的东西 S2E6 病例.18「山田喜欢我」' item_id = '70758' item_path = '/data/动漫/我心里危险的东西/Season 2/我心里危险的东西 - S02E06.mp4' season_id = 2 episode_id = 6 tmdb_id = 'None' overview = '市川被拜托在毕业典礼的彩排中诵读在校生代表的致辞。在山田期待的目光下,市川决定接受挑战,但由于紧张而无法发出声音。山田对沮丧的市川说:“我在上发声练习课”,给了他很多建议。偶然间,两人目睹了南条被女生...' percentage = 0.04525578333646793 ip = '192.168.10.254' device_name = 'Railgun-m-PC' client = 'Emby Theater' user_name = 'root_nas' image_url = 'https://image.tmdb.org/t/p/original/3hbvuY7ZQXsQjGC66JN6JTvRGC0.jpg' item_favorite = None save_reason = None item_isvirtual = None media_type = 'Episode'

香开的

event = 'playback.pause' channel = 'emby' server_name = 'emby' item_type = 'TV' item_name = '香格里拉边境 S2E4 人行走于天空之时,会梦想不可能之事' item_id = '62397' item_path = '/data/动漫/香格里拉边境/Season 2/香格里拉边境 - S02E04.mkv' season_id = 2 episode_id = 4 tmdb_id = 'None' overview = '根据潘希鲁贡的提案,「旅狼」、「SF-Zoo」、「图书馆」、「黑狼」这四个公会组成了临时战队联盟。会议结束后,桑乐与隶属于旅狼的两人道别,桑乐决定在前往拉比兹之前,再度前往「水晶巢崖」这个冒险之地,寻...' percentage = 0.04402210106377368 ip = '192.168.10.254' device_name = 'Railgun-m-PC' client = 'Emby Theater' user_name = 'root_nas' image_url = 'https://image.tmdb.org/t/p/original/3uD19dEs26MbsikvufLTyldJYzx.jpg' item_favorite = None save_reason = None item_isvirtual = None media_type = 'Episode'

l429609201 avatar May 14 '25 08:05 l429609201

看起来 season_id 和 episode_id 都传过来了呀

happyTonakai avatar May 14 '25 08:05 happyTonakai

抛出的报错问题已经解决,是int类型转换的问题,目前测试未见其他报错 详情见

https://github.com/l429609201/MoviePilot-Plugins/blob/main/plugins/bangumisyncdebug/init.py

            unique_id = int(tmdb_id) if tmdb_id else None

改成

            unique_id = tmdb_id if isinstance(tmdb_id, int) else None

l429609201 avatar May 14 '25 09:05 l429609201

那你的tmdb_id传进来到底是啥。。既不是int也不是空

哦,看到了,是'None'...

happyTonakai avatar May 14 '25 09:05 happyTonakai

我看下,我是用的叮叮当大佬的插件刮的

Image

nfo里面是None

l429609201 avatar May 14 '25 09:05 l429609201

干脆这样吧

try:
    unique_id = int(tmdb_id)
except Exception:
    unique_id = None

我也没见过单集刮出来是什么样,万一再是 '123' 这样的str,给忽略了就不好了

另外关于之前说的season_id和episode_id如果没有的问题,这个我看了下mp里面的实现,item_name也是基于这两个拼出来的,如果没有的话基本上就点不了了

happyTonakai avatar May 14 '25 09:05 happyTonakai

可以的,你可以改动一下代码,我重载测试一下

l429609201 avatar May 14 '25 09:05 l429609201