diff --git a/internal/service/stream.go b/internal/service/stream.go index 1f5f4de..fe8c3f6 100644 --- a/internal/service/stream.go +++ b/internal/service/stream.go @@ -15,572 +15,3 @@ // GET /api/hls/:id/index.m3u8 → HLS playlist // GET /api/hls/:id/seg_NNNNN.ts → HLS segment package service - -import ( - "context" - "errors" - "io" - "net/http" - "net/url" - "os" - "path/filepath" - "strings" - "time" - - "go.uber.org/zap" - - "github.com/ShukeBta/MediaStationGo/internal/config" - "github.com/ShukeBta/MediaStationGo/internal/model" - "github.com/ShukeBta/MediaStationGo/internal/repository" -) - -const ( - STRMEnabledSettingKey = "strm.enabled" - CloudPlaybackModeSettingKey = "cloud.playback_mode" - CloudPlaybackSTRMEnabledSettingKey = "cloud.playback_strm_enabled" - CloudPlaybackRedirectEnabledSettingKey = "cloud.playback_redirect_proxy_enabled" - - CloudPlaybackModeSTRM = "strm" - CloudPlaybackModeRedirectProxy = "redirect_proxy" -) - -type CloudPlaybackOptions struct { - STRMEnabled bool - RedirectProxyEnabled bool - PreferredMode string -} - -// StreamService serves media files with proper Range support so browsers can -// seek into the stream. -type StreamService struct { - cfg *config.Config - log *zap.Logger - repo *repository.Container - transcoder *TranscoderService -} - -// NewStreamService is the constructor. -func NewStreamService(cfg *config.Config, log *zap.Logger, repo *repository.Container, transcoder *TranscoderService) *StreamService { - return &StreamService{ - cfg: cfg, - log: log, - repo: repo, - transcoder: transcoder, - } -} - -// ErrMediaNotFound is returned when the media row or its file is missing. -var ErrMediaNotFound = errors.New("media not found") - -// ErrCloudPlaybackUnavailable 表示媒体行存在但属于云盘媒体、且当前无法 -// 构造可用的播放重定向(通常是 STRMURL 缺失,需要重新扫描媒体库)。 -// 调用方应把它与「媒体不存在」区分开,避免把配置类故障当成 404 返回给播放器。 -var ErrCloudPlaybackUnavailable = errors.New("cloud media playback unavailable: media missing play url; re-scan the library") - -var ErrCloudPlaybackDisabled = errors.New("cloud media playback disabled by admin settings") - -// normalizeCloudPlayTarget 把存库的云盘播放 URL 规范化为相对路径。 -// -// STRMURL 是扫描时根据当时的 server_url/请求地址生成并固化进数据库的。 -// 在 Windows 开发机上扫描、再部署到 Docker(或更换了内网 IP/域名)后, -// 这些绝对 URL 会指向已失效的旧地址,第三方播放器跟随 302 就会拿到 -// 连接失败/404。这里只要能从 URL 中解析出 provider+ref,就重建为相对 -// /api/cloud/play 路径,由 absoluteInternalRedirect 基于「当前请求」补全 -// host,从而对历史脏数据免疫。 -func normalizeCloudPlayTarget(raw string) string { - typ, ref, ok := parseCloudMediaPlaybackURL(raw) - if !ok { - return raw - } - return BuildRelativeCloudPlayURL(typ, ref) -} - -// BuildRelativeCloudPlayURL 构造相对的云盘播放 API 路径。 -func BuildRelativeCloudPlayURL(typ, ref string) string { - return "/api/cloud/play/" + url.PathEscape(strings.TrimSpace(typ)) + "?" + url.Values{"ref": []string{ref}}.Encode() -} - -// directPlayOnly reports whether the admin enabled「客户端直连解码」mode, -// in which the host never transcodes (HLS is refused) and all playback is -// handled by the client (direct play / 302 redirect). -func (s *StreamService) directPlayOnly(ctx context.Context) bool { - if s.repo == nil || s.repo.Setting == nil { - return false - } - v, err := s.repo.Setting.Get(ctx, PlaybackDirectOnlySettingKey) - if err != nil { - return false - } - return parseBoolSetting(v, false) -} - -// withAuthToken propagates the caller's auth token onto an internal redirect -// target. A browser