add mv-audio-type mv-max
This commit is contained in:
parent
60942cd286
commit
560a6b45f4
@ -42,3 +42,5 @@ apple-master-choice : "[M]"
|
||||
use-songinfo-for-playlist: false
|
||||
#if set true,will download album cover for playlist
|
||||
dl-albumcover-for-playlist: false
|
||||
mv-audio-type: atmos #atmos ac3 aac
|
||||
mv-max: 2160
|
||||
|
99
main.go
99
main.go
@ -44,6 +44,8 @@ var (
|
||||
debug_mode bool
|
||||
alac_max *int
|
||||
atmos_max *int
|
||||
mv_max *int
|
||||
mv_audio_type *string
|
||||
aac_type *string
|
||||
Config structs.ConfigSet
|
||||
counter structs.Counter
|
||||
@ -100,7 +102,7 @@ func checkUrl(url string) (string, string) {
|
||||
return matches[0][1], matches[0][2]
|
||||
}
|
||||
}
|
||||
func checkUrlMv(url string) (string) {
|
||||
func checkUrlMv(url string) string {
|
||||
pat := regexp.MustCompile(`^(?:https:\/\/(?:beta\.music|music)\.apple\.com\/(\w{2})(?:\/music-video|\/music-video\/.+))\/(?:id)?(\d[^\D]+)(?:$|\?)`)
|
||||
matches := pat.FindAllStringSubmatch(url, -1)
|
||||
|
||||
@ -1104,6 +1106,8 @@ func main() {
|
||||
alac_max = pflag.Int("alac-max", Config.AlacMax, "Specify the max quality for download alac")
|
||||
atmos_max = pflag.Int("atmos-max", Config.AtmosMax, "Specify the max quality for download atmos")
|
||||
aac_type = pflag.String("aac-type", Config.AacType, "Select AAC type, aac aac-binaural aac-downmix")
|
||||
mv_audio_type = pflag.String("mv-audio-type", Config.MVAudioType, "Select MV audio type, atmos ac3 aac")
|
||||
mv_max = pflag.Int("mv-max", Config.MVMax, "Specify the max quality for download MV")
|
||||
|
||||
// Custom usage message for help
|
||||
pflag.Usage = func() {
|
||||
@ -1117,6 +1121,8 @@ func main() {
|
||||
Config.AlacMax = *alac_max
|
||||
Config.AtmosMax = *atmos_max
|
||||
Config.AacType = *aac_type
|
||||
Config.MVAudioType = *mv_audio_type
|
||||
Config.MVMax = *mv_max
|
||||
|
||||
args := pflag.Args()
|
||||
if len(args) == 0 {
|
||||
@ -1209,10 +1215,10 @@ func main() {
|
||||
counter = structs.Counter{}
|
||||
}
|
||||
}
|
||||
func mvDownloader(adamID string, saveDir string, token string, mediaUserToken string)(error){
|
||||
func mvDownloader(adamID string, saveDir string, token string, mediaUserToken string) error {
|
||||
vidPath := filepath.Join(saveDir, fmt.Sprintf("%s_vid.mp4", adamID))
|
||||
audPath := filepath.Join(saveDir, fmt.Sprintf("%s_aud.mp4", adamID))
|
||||
mvOutPath := filepath.Join(saveDir, fmt.Sprintf("%s.mkv", adamID))
|
||||
mvOutPath := filepath.Join(saveDir, fmt.Sprintf("%s.mp4", adamID))
|
||||
exists, _ := fileExists(mvOutPath)
|
||||
if exists {
|
||||
fmt.Println("MV already exists locally.")
|
||||
@ -1222,7 +1228,6 @@ func mvDownloader(adamID string, saveDir string, token string, mediaUserToken st
|
||||
//videom3u8url, audiom3u8url , _ := mvQualitySelect(mvm3u8url)
|
||||
videom3u8url, _ := extractVideo(mvm3u8url)
|
||||
audiom3u8url, _ := extractMvAudio(mvm3u8url)
|
||||
//fmt.Println(videom3u8url)
|
||||
//fmt.Println(audiom3u8url)
|
||||
|
||||
videokeyAndUrls, _ := runv3.Run(adamID, videom3u8url, token, mediaUserToken, true)
|
||||
@ -1255,37 +1260,77 @@ func extractMvAudio(c string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := http.Get(c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
videoString := string(body)
|
||||
from, listType, err := m3u8.DecodeFrom(strings.NewReader(videoString), true)
|
||||
if err != nil || listType != m3u8.MASTER {
|
||||
return "", errors.New("m3u8 not of media type")
|
||||
}
|
||||
|
||||
video := from.(*m3u8.MasterPlaylist)
|
||||
var streamUrl *url.URL
|
||||
|
||||
var audioPriority = []string{"audio-atmos", "audio-ac3", "audio-stereo-256"}
|
||||
if Config.MVAudioType == "ac3" {
|
||||
audioPriority = []string{"audio-ac3", "audio-stereo-256"}
|
||||
} else if Config.MVAudioType == "aac" {
|
||||
audioPriority = []string{"audio-stereo-256"}
|
||||
}
|
||||
|
||||
re := regexp.MustCompile(`_gr(\d+)_`)
|
||||
|
||||
type AudioStream struct {
|
||||
URL string
|
||||
Rank int
|
||||
GroupID string
|
||||
}
|
||||
var audioStreams []AudioStream
|
||||
|
||||
for _, variant := range video.Variants {
|
||||
for _, audiov := range variant.Alternatives {
|
||||
if audiov.GroupId == "audio-stereo-256" {
|
||||
streamUrl, _ = MediaUrl.Parse(audiov.URI)
|
||||
break
|
||||
if audiov.URI != "" {
|
||||
for _, priority := range audioPriority {
|
||||
if audiov.GroupId == priority {
|
||||
matches := re.FindStringSubmatch(audiov.URI)
|
||||
if len(matches) == 2 {
|
||||
var rank int
|
||||
fmt.Sscanf(matches[1], "%d", &rank)
|
||||
streamUrl, _ := MediaUrl.Parse(audiov.URI)
|
||||
audioStreams = append(audioStreams, AudioStream{
|
||||
URL: streamUrl.String(),
|
||||
Rank: rank,
|
||||
GroupID: audiov.GroupId,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if streamUrl == nil {
|
||||
return "", errors.New("no video codec found")
|
||||
}
|
||||
return streamUrl.String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(audioStreams) == 0 {
|
||||
return "", errors.New("no suitable audio stream found")
|
||||
}
|
||||
|
||||
sort.Slice(audioStreams, func(i, j int) bool {
|
||||
return audioStreams[i].Rank > audioStreams[j].Rank
|
||||
})
|
||||
|
||||
return audioStreams[0].URL, nil
|
||||
}
|
||||
|
||||
func conventSyllableTTMLToLRC(ttml string) (string, error) {
|
||||
@ -1775,38 +1820,62 @@ func extractVideo(c string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := http.Get(c)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", errors.New(resp.Status)
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
videoString := string(body)
|
||||
|
||||
from, listType, err := m3u8.DecodeFrom(strings.NewReader(videoString), true)
|
||||
if err != nil || listType != m3u8.MASTER {
|
||||
return "", errors.New("m3u8 not of media type")
|
||||
}
|
||||
|
||||
video := from.(*m3u8.MasterPlaylist)
|
||||
|
||||
re := regexp.MustCompile(`_(\d+)x(\d+)_`)
|
||||
|
||||
var streamUrl *url.URL
|
||||
sort.Slice(video.Variants, func(i, j int) bool {
|
||||
return video.Variants[i].AverageBandwidth > video.Variants[j].AverageBandwidth
|
||||
})
|
||||
if len(video.Variants) > 0 {
|
||||
highestBandwidthVariant := video.Variants[0]
|
||||
streamUrl, err = MediaUrl.Parse(highestBandwidthVariant.URI)
|
||||
|
||||
maxHeight := Config.MVMax
|
||||
|
||||
for _, variant := range video.Variants {
|
||||
matches := re.FindStringSubmatch(variant.URI)
|
||||
if len(matches) == 3 {
|
||||
height := matches[2]
|
||||
var h int
|
||||
_, err := fmt.Sscanf(height, "%d", &h)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if h <= maxHeight {
|
||||
streamUrl, err = MediaUrl.Parse(variant.URI)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if streamUrl == nil {
|
||||
return "", errors.New("no video codec found")
|
||||
return "", errors.New("no suitable video stream found")
|
||||
}
|
||||
|
||||
return streamUrl.String(), nil
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,8 @@ type ConfigSet struct {
|
||||
LimitMax int `yaml:"limit-max"`
|
||||
UseSongInfoForPlaylist bool `yaml:"use-songinfo-for-playlist"`
|
||||
DlAlbumcoverForPlaylist bool `yaml:"dl-albumcover-for-playlist"`
|
||||
MVAudioType string `yaml:"mv-audio-type"`
|
||||
MVMax int `yaml:"mv-max"`
|
||||
}
|
||||
|
||||
type Counter struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user