Files
ggjuku/internal/app/download_quality.go
2026-09-30 10:19:54 +08:00

94 lines
3.0 KiB
Go

package app
import (
"context"
"encoding/json"
"io"
"net/http"
)
func readDownloadRequest(writer http.ResponseWriter, request *http.Request) ([]string, *int, bool) {
var input struct {
IDs []string `json:"ids"`
Quality *int `json:"quality"`
}
decoder := json.NewDecoder(http.MaxBytesReader(writer, request.Body, 1<<20))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&input); err != nil {
writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "下载参数无效"})
return nil, nil, false
}
if decoder.Decode(new(any)) != io.EOF || input.Quality != nil && (*input.Quality < 0 || *input.Quality > 4320) {
writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "下载清晰度选项无效"})
return nil, nil, false
}
ids, ok := cleanIDList(writer, input.IDs)
if !ok {
return nil, nil, false
}
for index, id := range ids {
_, sourceID, valid := splitProviderDramaID(id)
if !valid {
writeJSON(writer, http.StatusBadRequest, map[string]string{"error": "此版本仅支持红果剧集 ID"})
return nil, nil, false
}
ids[index] = providerDramaID(sourceHongguo, sourceID)
}
return ids, input.Quality, true
}
func preferredDownloadQuality(requested int, available []int) int {
best, lowest := 0, 0
for _, quality := range available {
if quality <= 0 || quality > 4320 {
continue
}
if lowest == 0 || quality < lowest {
lowest = quality
}
if (requested <= 0 || quality <= requested) && quality > best {
best = quality
}
}
if best == 0 {
return lowest
}
return best
}
func (downloader *Downloader) selectDownloadQuality(ctx context.Context, task Task, media providerMedia) (providerMedia, error) {
qualities := []int{media.Quality}
validVariants := make([]providerMedia, 0, len(media.Variants)+1)
for _, variant := range media.Variants {
if isProviderHTTPMediaURL(variant.URL) {
qualities = append(qualities, variant.Quality)
validVariants = append(validVariants, variant)
}
}
if isProviderHTTPMediaURL(media.URL) {
current := media
current.Variants = nil
validVariants = append(validVariants, current)
}
media.Variants = validVariants
if variants := playbackHLSVariants(media.Playlist); len(variants) > 0 {
qualities = nil
for _, variant := range variants {
qualities = append(qualities, variant.quality)
}
}
quality := preferredDownloadQuality(task.DownloadQuality, qualities)
selected, err := downloader.selectPlaybackQuality(context.WithValue(ctx, playbackQualityKey{}, quality), media)
if err != nil {
return providerMedia{}, err
}
var available []int
for _, option := range playbackQualityOptions(selected) {
available = append(available, option.Value)
}
downloader.recordDiagnostic(diagnosticEvent{Level: "info", Event: "download.media", Source: sourceFromDramaID(task.DramaID),
DramaID: task.DramaID, DramaTitle: task.DramaTitle, Episode: task.Index, Quality: selected.Quality, RequestedQuality: task.DownloadQuality, AvailableQualities: available,
Message: "下载保留源媒体的音视频编码和分辨率"})
return selected, nil
}