Files
MeBox/internal/service/runtime_settings.go
T
soldosluka857 e50282178d feat(playback): client direct-play decode mode (release host transcoding)
Add an admin toggle playback.direct_only that offloads all decoding to the
client. When enabled:
- Emby PlaybackInfo no longer advertises SupportsTranscoding nor a
  TranscodingUrl, forcing Emby/Infuse/Yamby clients to direct play.
- HLS endpoints refuse (ErrTranscodeDisabled) so the host never spawns ffmpeg.
- Web player forces direct play, hides the HLS toggle, and surfaces a hint.
Exposed via /system/info (direct_play_only) and the Settings page.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 21:04:23 +08:00

94 lines
2.7 KiB
Go

package service
import (
"context"
"strconv"
"strings"
"go.uber.org/zap"
"github.com/ShukeBta/MediaStationGo/internal/config"
"github.com/ShukeBta/MediaStationGo/internal/repository"
)
func ApplyRuntimeSettings(ctx context.Context, cfg *config.Config, repos *repository.Container, log *zap.Logger) {
if cfg == nil || repos == nil || repos.Setting == nil {
return
}
rows, err := repos.Setting.All(ctx)
if err != nil {
if log != nil {
log.Warn("load runtime settings failed", zap.Error(err))
}
return
}
for _, row := range rows {
ApplyRuntimeSetting(cfg, row.Key, row.Value)
}
}
func ApplyRuntimeSetting(cfg *config.Config, key, value string) {
if cfg == nil {
return
}
value = strings.TrimSpace(value)
switch key {
case "ffmpeg.path", "app.ffmpeg_path":
cfg.App.FFmpegPath = value
case "ffprobe.path", "app.ffprobe_path":
cfg.App.FFprobePath = value
case "transcode.enabled", "transcoder.enabled":
cfg.Transcoder.Enabled = parseBoolSetting(value, true)
case "transcode.hw_enabled", "transcoder.hardware_accel":
cfg.Transcoder.HardwareAccel = parseBoolSetting(value, false)
case "transcode.hw_accel", "transcoder.encoder":
switch value {
case "", "auto", "none", "software":
cfg.Transcoder.Encoder = ""
case "nvenc", "qsv", "vaapi":
cfg.Transcoder.Encoder = value
}
case "transcode.max_height", "transcoder.max_height":
if n, err := strconv.Atoi(value); err == nil {
cfg.Transcoder.MaxHeight = n
}
case "transcode.max_jobs", "transcoder.max_concurrent":
if n, err := strconv.Atoi(value); err == nil {
cfg.Transcoder.MaxConcurrent = n
}
case "transcode.realtime", "transcoder.realtime":
cfg.Transcoder.Realtime = parseBoolSetting(value, true)
case "transcode.threads", "transcoder.threads":
if n, err := strconv.Atoi(value); err == nil {
cfg.Transcoder.Threads = n
}
case "transcode.idle_timeout_seconds", "transcoder.idle_timeout_seconds":
if n, err := strconv.Atoi(value); err == nil {
cfg.Transcoder.IdleTimeoutSeconds = n
}
case "transcode.video_bitrate", "transcoder.video_bitrate":
cfg.Transcoder.VideoBitrate = value
case "license.server_url":
cfg.License.ServerURL = value
case "license.hmac_secret":
cfg.License.HMACSecret = value
}
}
// ParseBoolSetting is the exported variant of parseBoolSetting for handlers
// that need to interpret persisted on/off settings (accepts zh + en tokens).
func ParseBoolSetting(value string, fallback bool) bool {
return parseBoolSetting(value, fallback)
}
func parseBoolSetting(value string, fallback bool) bool {
switch strings.ToLower(strings.TrimSpace(value)) {
case "1", "true", "yes", "on", "enabled", "启用", "开启":
return true
case "0", "false", "no", "off", "disabled", "禁用", "关闭":
return false
default:
return fallback
}
}