2021-09-24 05:15:40 +00:00
|
|
|
package youtube
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
youtubev2 "github.com/kkdai/youtube/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
func FormatDebugString(format *youtubev2.Format, includeURL bool) string {
|
|
|
|
var url string
|
|
|
|
if includeURL {
|
|
|
|
url = format.URL
|
|
|
|
}
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"iTag = %d, mime_type = %s, quality = %s, quality_label = %s, bitrate = %d, fps = %d, width = %d, height = %d, content_length = %d, duration = %v, audio_channels = %d, audio_sample_rate = %s, audio_quality = %s, url = %s",
|
|
|
|
format.ItagNo,
|
|
|
|
format.MimeType,
|
|
|
|
format.Quality,
|
|
|
|
format.QualityLabel,
|
|
|
|
format.Bitrate,
|
|
|
|
format.FPS,
|
|
|
|
format.Width,
|
|
|
|
format.Height,
|
|
|
|
format.ContentLength,
|
|
|
|
format.ApproxDurationMs,
|
|
|
|
format.AudioChannels,
|
|
|
|
format.AudioSampleRate,
|
|
|
|
format.AudioQuality,
|
|
|
|
url,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SortAudio returns the provided formats ordered in descending preferred
|
|
|
|
// order. The ideal candidate is 44.1kHz stereo audio in a webm container, with
|
|
|
|
// the highest available bitrate.
|
|
|
|
func SortAudio(inFormats youtubev2.FormatList) youtubev2.FormatList {
|
|
|
|
// TODO: sort in-place.
|
|
|
|
var formats youtubev2.FormatList
|
|
|
|
for _, format := range inFormats {
|
|
|
|
if format.FPS == 0 && format.AudioChannels > 0 {
|
|
|
|
formats = append(formats, format)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.SliceStable(formats, func(i, j int) bool {
|
|
|
|
isOpusI := strings.Contains(formats[i].MimeType, "opus")
|
|
|
|
isOpusJ := strings.Contains(formats[j].MimeType, "opus")
|
|
|
|
if isOpusI && isOpusJ {
|
|
|
|
isStereoI := formats[i].AudioChannels == 2
|
|
|
|
isStereoJ := formats[j].AudioChannels == 2
|
|
|
|
if isStereoI && isStereoJ {
|
2021-09-24 05:37:27 +00:00
|
|
|
is48kI := formats[i].AudioSampleRate == "48000"
|
|
|
|
is48kJ := formats[j].AudioSampleRate == "48000"
|
|
|
|
if is48kI && is48kJ {
|
2021-09-24 05:15:40 +00:00
|
|
|
return formats[i].Bitrate > formats[j].Bitrate
|
|
|
|
}
|
2021-09-24 05:37:27 +00:00
|
|
|
return is48kI
|
2021-09-24 05:15:40 +00:00
|
|
|
}
|
|
|
|
return isStereoI
|
|
|
|
}
|
|
|
|
return isOpusI
|
|
|
|
})
|
|
|
|
return formats
|
|
|
|
}
|
|
|
|
|
|
|
|
// SortVideo returns the provided formats ordered in descending preferred
|
|
|
|
// order. The ideal candidate is video in an mp4 container with a medium
|
|
|
|
// bitrate, with audio channels (needed to allow synced playback on the
|
|
|
|
// website).
|
|
|
|
func SortVideo(inFormats youtubev2.FormatList) youtubev2.FormatList {
|
|
|
|
// TODO: sort in-place.
|
|
|
|
var formats youtubev2.FormatList
|
|
|
|
for _, format := range inFormats {
|
|
|
|
if format.FPS > 0 && format.AudioChannels > 0 {
|
|
|
|
formats = append(formats, format)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.SliceStable(formats, func(i, j int) bool {
|
|
|
|
isMP4I := strings.Contains(formats[i].MimeType, "mp4")
|
|
|
|
isMP4J := strings.Contains(formats[j].MimeType, "mp4")
|
|
|
|
if isMP4I && isMP4J {
|
|
|
|
return compareQualityLabel(formats[i].QualityLabel, formats[j].QualityLabel)
|
|
|
|
}
|
|
|
|
return strings.Contains(formats[i].MimeType, "mp4")
|
|
|
|
})
|
|
|
|
return formats
|
|
|
|
}
|
|
|
|
|
|
|
|
func compareQualityLabel(a, b string) bool {
|
|
|
|
return (a == "360p" || a == "480p") && (b != "360p" && b != "480p")
|
|
|
|
}
|