ShuffleDepth in DiskProfile controls how files are selected:
-1 = no shuffle (preserve source order)
0 = all files in random order
N = group files by folder at depth N from /media, shuffle groups,
copy entire group before moving to next
Exposed in disk profile UI as a select with level descriptions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
74 lines
2.2 KiB
Go
74 lines
2.2 KiB
Go
package disk
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
type DiskProfile struct {
|
|
DestFolder string `json:"dest_folder"`
|
|
OverwriteMode string `json:"overwrite_mode"`
|
|
FileSelectMode string `json:"file_select_mode"`
|
|
ReserveFreeGB float64 `json:"reserve_free_gb"`
|
|
AutoCopy bool `json:"auto_copy"`
|
|
// ShuffleDepth: -1=выкл, 0=файлы вразнобой, 1+=папки на глубине N от корня /media
|
|
ShuffleDepth int `json:"shuffle_depth"`
|
|
|
|
// nil = не транскодировать видео
|
|
Transcode *TranscodeProfile `json:"transcode,omitempty"`
|
|
}
|
|
|
|
type TranscodeProfile struct {
|
|
VideoCodec string `json:"video_codec"` // "h264" | "h265" | "mpeg4"
|
|
MaxResolution string `json:"max_resolution"` // "480p" | "720p" | "1080p"
|
|
MaxVideoBitrate string `json:"max_video_bitrate"` // "1000k" | "2000k" | "" (без лимита)
|
|
MaxFPS int `json:"max_fps"` // 0=без лимита | 24 | 25 | 30
|
|
AudioCodec string `json:"audio_codec"` // "aac" | "mp3"
|
|
MaxAudioBitrate string `json:"max_audio_bitrate"` // "128k" | "192k" | ""
|
|
MaxAudioChannels int `json:"max_audio_channels"` // 2=стерео | 6=5.1
|
|
OutputFormat string `json:"output_format"` // "mp4" | "mkv" | "avi"
|
|
}
|
|
|
|
const profileFile = "profile.json"
|
|
|
|
func profilePath(mountPath string) string {
|
|
return filepath.Join(mountPath, MarkerDir, profileFile)
|
|
}
|
|
|
|
func LoadProfile(mountPath string) (*DiskProfile, error) {
|
|
data, err := os.ReadFile(profilePath(mountPath))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var p DiskProfile
|
|
if err := json.Unmarshal(data, &p); err != nil {
|
|
return nil, err
|
|
}
|
|
return &p, nil
|
|
}
|
|
|
|
func SaveProfile(mountPath string, p *DiskProfile) error {
|
|
data, err := json.MarshalIndent(p, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
path := profilePath(mountPath)
|
|
tmp := path + ".tmp"
|
|
if err := os.WriteFile(tmp, data, 0o644); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(tmp, path)
|
|
}
|
|
|
|
func DefaultProfile() *DiskProfile {
|
|
return &DiskProfile{
|
|
DestFolder: "media",
|
|
OverwriteMode: "skip",
|
|
FileSelectMode: "new",
|
|
ReserveFreeGB: 2.0,
|
|
AutoCopy: false,
|
|
ShuffleDepth: -1,
|
|
}
|
|
}
|