修改 Jellyfin 背景随机播放的方法

通过修改 Jellyfin 的 `main.jellyfin.bundle.js` 文件,使 backdrops 文件夹中的媒体在背景中随机播放。

概要

Jellyfin 中并没有直接支持让背景随机播放的功能或开关。 以下是通过修改 main.jellyfin.bundle.js 文件,实现 backdrops 文件夹里的媒体在背景中随机播放。 此方法主要参考了 Allow Backdrop Shuffling 的实现方式。 alt ⚠️ 注意:main.jellyfin.bundle.js 文件的内容因版本而异,此方法适用于 Jellyfin 10.10.3 版本。


修改步骤

这里有已经修改好的文件:Jellyfin_random_backdrops

1. 找到文件路径

在 Windows 中,main.jellyfin.bundle.js 文件的默认路径为:

1
C:\Program Files\Jellyfin\Server\jellyfin-web

linux 等系统的路径应类似,俺也不知道(


2. 打开并格式化代码

打开main.jellyfin.bundle.js后你会发现这是一坨没有缩进的代码…请使用惯用的工具(如 VS Code)将其进行auto format, 然后尝试定位如下关键字: function G(){var e;return e=z().mark 同时这个G()函数结尾关键字为: a(void 0)}))},G.apply(this,arguments)}

G()函数的完整内容如下:

1
function G(){var e;return e=z().mark((function e(t,n){var r,i,a,s,l,u,c,d;return z().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=o.A.getApiClient(t),i=(0,_.C)(r),a=r.getCurrentUserId(),e.prev=3,e.next=6,j.q.fetchQuery((0,L.I)(i,a,n));case 6:if(!(l=e.sent).CollectionType){e.next=10;break}return q(),e.abrupt("return");case 10:if(!H.includes(l.Type)){e.next=13;break}return q(),e.abrupt("return");case 13:return e.next=15,(0,D.Q)(i).getThemeMedia({userId:a,itemId:l.Id,inheritFromParent:!0});case 15:u=e.sent,c=u.data,(d=m.currentSettings.enableThemeVideos()&&null!==(s=c.ThemeVideosResult)&&void 0!==s&&null!==(s=s.Items)&&void 0!==s&&s.length?c.ThemeVideosResult:c.ThemeSongsResult).OwnerId!==M&&B(d.Items,d.OwnerId),e.next=24;break;case 21:e.prev=21,e.t0=e.catch(3),console.error("[ThemeMediaPlayer] failed to load theme media",e.t0);case 24:case"end":return e.stop()}}),e,null,[[3,21]])})),G=function(){var t=this,n=arguments;return new Promise((function(r,i){var o=e.apply(t,n);function a(e){U(o,r,i,a,s,"next",e)}function s(e){U(o,r,i,a,s,"throw",e)}a(void 0)}))},G.apply(this,arguments)}

3. 替换为修改后的函数

将上述 G() 函数从头到尾替换为以下代码,替换完成后删除所有缩进,注意不要添加注释:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
function shuffle(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
}
function G() {
    var e;
    return e = z().mark(function e(t, n) {
        var r, i, a, s, l, u, c, d;
        return z().wrap(function(e) {
            for (;;) switch (e.prev = e.next) {
                case 0:
                    return r = o.A.getApiClient(t),
                           i = (0, _.C)(r),
                           a = r.getCurrentUserId(),
                           e.prev = 3,
                           e.next = 6,
                           j.q.fetchQuery((0, L.I)(i, a, n));
                case 6:
                    if (!(l = e.sent).CollectionType) {
                        e.next = 10;
                        break;
                    }
                    return q(), e.abrupt("return");
                case 10:
                    if (!H.includes(l.Type)) {
                        e.next = 13;
                        break;
                    }
                    return q(), e.abrupt("return");
                case 13:
                    return e.next = 15, (0, D.Q)(i).getThemeMedia({
                        userId: a,
                        itemId: l.Id,
                        inheritFromParent: !0
                    });
                case 15:
                    u = e.sent,
                    c = u.data,
                    (d = m.currentSettings.enableThemeVideos() && 
                        null !== (s = c.ThemeVideosResult) && 
                        void 0 !== s && 
                        null !== (s = s.Items) && 
                        void 0 !== s && 
                        s.length ? 
                            { ...c.ThemeVideosResult, Items: shuffle(s) } : 
                            c.ThemeSongsResult
                    ).OwnerId !== M && B(d.Items, d.OwnerId),
                    e.next = 24;
                    break;
                case 21:
                    e.prev = 21, 
                    e.t0 = e.catch(3), 
                    console.error("[ThemeMediaPlayer] failed to load theme media", e.t0);
                case 24:
                case "end":
                    return e.stop();
            }
        }, e, null, [
            [3, 21]
        ]);
    }), G = function() {
        var t = this,
            n = arguments;
        return new Promise(function(r, i) {
            var o = e.apply(t, n);
            function a(e) {
                U(o, r, i, a, s, "next", e);
            }
            function s(e) {
                U(o, r, i, a, s, "throw", e);
            }
            a(void 0);
        });
    }, G.apply(this, arguments);
}

代码分析

主要关注 case 15 的逻辑:

1
2
3
4
5
6
7
(d = m.currentSettings.enableThemeVideos() && 
    null !== (s = c.ThemeVideosResult) && 
    void 0 !== s && 
    null !== (s = s.Items) && 
    void 0 !== s && 
    s.length ? c.ThemeVideosResult : c.ThemeSongsResult
).OwnerId !== M && B(d.Items, d.OwnerId);

判断是否启用ThemeVideo,以及ThemeVideosResult.Items是否存在并且由内容, 如果是则使用ThemeVideosResult为d赋值, 并且进行播放B(d.Items, d.OwnerId)

修改后则是在获取 ThemeVideosResult.Items 后,直接调用 shuffle 对数组进行打乱:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(d = m.currentSettings.enableThemeVideos() && 
    null !== (s = c.ThemeVideosResult) && 
    void 0 !== s && 
    null !== (s = s.Items) && 
    void 0 !== s && 
    s.length ? 
        { ...c.ThemeVideosResult, Items: shuffle(s) } : 
        c.ThemeSongsResult
).OwnerId !== M && B(d.Items, d.OwnerId),
e.next = 24;
break;
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus