From 93c7487c96a93c47f9190744a80e9bd35a1bf782 Mon Sep 17 00:00:00 2001 From: truewhile <62226914+truewhile@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:16:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=92=AD=E6=94=BE=E4=BD=93?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化播放体验 --- internal/service/stream_file.go | 15 +++++++++++++++ internal/service/transcoder.go | 6 ++++++ web/src/pages/playerPageModel.ts | 4 ++++ 3 files changed, 25 insertions(+) diff --git a/internal/service/stream_file.go b/internal/service/stream_file.go index eefacce..1529646 100644 --- a/internal/service/stream_file.go +++ b/internal/service/stream_file.go @@ -86,6 +86,21 @@ func playableSTRMTarget(ctx context.Context, repo *repository.Container, raw str return STRMPlaybackEnabled(ctx, repo) } +// isStrmMediaRow 判断媒体行是否为 .strm(远程直链)媒体:STRMURL 非空、 +// container=strm 或路径以 .strm 结尾。strm 媒体只能直连播放,禁止转码。 +func isStrmMediaRow(m *model.Media) bool { + if m == nil { + return false + } + if strings.TrimSpace(m.STRMURL) != "" { + return true + } + if strings.EqualFold(strings.TrimSpace(m.Container), "strm") { + return true + } + return strings.HasSuffix(strings.ToLower(strings.TrimSpace(m.Path)), ".strm") +} + func isHTTPPlaybackTarget(raw string) bool { u, err := url.Parse(strings.TrimSpace(raw)) if err != nil || u == nil || !u.IsAbs() { diff --git a/internal/service/transcoder.go b/internal/service/transcoder.go index ec4069b..b9bfc2d 100644 --- a/internal/service/transcoder.go +++ b/internal/service/transcoder.go @@ -101,6 +101,12 @@ func (t *TranscoderService) EnsureJob(ctx context.Context, mediaID string) (stri if m == nil { return "", ErrMediaNotFound } + // .strm 媒体(STRMURL 或 container=strm / *.strm 路径)的内容是远程 + // 直链文本,ffmpeg 无法读取,转码必然失败且白白消耗资源。直接拒绝 + // 转码,迫使播放器走 /api/stream 302 直连播放。 + if isStrmMediaRow(m) { + return "", ErrTranscodeDisabled + } if _, err := os.Stat(m.Path); err != nil { return "", ErrMediaNotFound } diff --git a/web/src/pages/playerPageModel.ts b/web/src/pages/playerPageModel.ts index d067c84..fcb03ed 100644 --- a/web/src/pages/playerPageModel.ts +++ b/web/src/pages/playerPageModel.ts @@ -12,6 +12,10 @@ export function pickPlayerMode(media: Media): PlayerMode { export function needsTranscodeForBrowser(media: Media): boolean { const container = (media.container ?? '').toLowerCase() + // .strm 媒体内容是远程直链(服务端 302 到播放 CDN 或反向代理), + // 浏览器直接播放该远程流即可,转码无意义且必然失败(ffmpeg 无法读取 + // 文本 strm),恒走 direct play。 + if (container.includes('strm') || String(media.strm_url ?? '').trim() !== '') return false const videoCodec = (media.video_codec ?? '').toLowerCase() const audioCodec = (media.audio_codec ?? '').toLowerCase() const containerOK = directContainers.some((item) => container.includes(item))