From c1c62ab94c2d6619bacfeae434136063e65ab804 Mon Sep 17 00:00:00 2001 From: zhaarey <157944548+zhaarey@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:58:17 +0800 Subject: [PATCH] add atmos and select to main.go --atmos,--select --- main.go | 519 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 348 insertions(+), 171 deletions(-) diff --git a/main.go b/main.go index 06cdc5e..9a2b8ee 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,8 @@ const ( var ( forbiddenNames = regexp.MustCompile(`[/\\<>:"|?*]`) ) +var dl_atmos = false +var dl_select = false type Config struct { MediaUserToken string `yaml:"media-user-token"` @@ -63,6 +65,7 @@ type Config struct { GetM3u8Port string `yaml:"get-m3u8-port"` GetM3u8FromDevice bool `yaml:"get-m3u8-from-device"` AlacMax int `yaml:"alac-max"` + AtmosMax int `yaml:"atmos-max"` UseSongInfoForPlaylist bool `yaml:"use-songinfo-for-playlist"` DlAlbumcoverForPlaylist bool `yaml:"dl-albumcover-for-playlist"` } @@ -109,6 +112,15 @@ func (*Alac) GetType() mp4.BoxType { return BoxTypeAlac() } +func isInArray(arr []int, target int) bool { + for _, num := range arr { + if num == target { + return true + } + } + return false +} + func fileExists(path string) (bool, error) { f, err := os.Stat(path) if err == nil { @@ -1009,6 +1021,14 @@ func decryptSong(info *SongInfo, keys []string, manifest *AutoGenerated, filenam return err } defer create.Close() + if dl_atmos { + _, err = create.Write(decrypted) + if err != nil { + panic(err) + } + + return nil + } return writeM4a(mp4.NewWriter(create), info, manifest, decrypted, trackNum, trackTotal) } @@ -1304,6 +1324,12 @@ func writeLyrics(sanAlbumFolder, filename string, lrc string) error { } func rip(albumId string, token string, storefront string, userToken string) error { + var Codec string + if dl_atmos { + Codec = "Atmos" + } else { + Codec = "ALAC" + } meta, err := getMeta(albumId, token, storefront) if err != nil { fmt.Println("Failed to get album metadata.\n") @@ -1336,20 +1362,24 @@ func rip(albumId string, token string, storefront string, userToken string) erro singerFolder := filepath.Join(config.AlacSaveFolder, forbiddenNames.ReplaceAllString(singerFoldername, "_")) var Quality string if strings.Contains(config.AlbumFolderFormat, "Quality") { - manifest1, err := getInfoFromAdam(meta.Data[0].Relationships.Tracks.Data[0].ID, token, storefront) - if err != nil { - fmt.Println("Failed to get manifest.\n", err) + if dl_atmos { + Quality = fmt.Sprintf("%dkbps", config.AtmosMax-2000) } else { - if manifest1.Attributes.ExtendedAssetUrls.EnhancedHls == "" { - fmt.Println("Unavailable in ALAC.\n") + manifest1, err := getInfoFromAdam(meta.Data[0].Relationships.Tracks.Data[0].ID, token, storefront) + if err != nil { + fmt.Println("Failed to get manifest.\n", err) } else { - EnhancedHls_m3u8, err := checkM3u8(meta.Data[0].Relationships.Tracks.Data[0].ID, "album") - if strings.HasPrefix(EnhancedHls_m3u8, "http") { - manifest1.Attributes.ExtendedAssetUrls.EnhancedHls = EnhancedHls_m3u8 - } - Quality, err = extractMediaQuality(manifest1.Attributes.ExtendedAssetUrls.EnhancedHls) - if err != nil { - fmt.Println("Failed to extract quality from manifest.\n", err) + if manifest1.Attributes.ExtendedAssetUrls.EnhancedHls == "" { + fmt.Println("Unavailable.\n") + } else { + EnhancedHls_m3u8, err := checkM3u8(meta.Data[0].Relationships.Tracks.Data[0].ID, "album") + if strings.HasPrefix(EnhancedHls_m3u8, "http") { + manifest1.Attributes.ExtendedAssetUrls.EnhancedHls = EnhancedHls_m3u8 + } + Quality, err = extractMediaQuality(manifest1.Attributes.ExtendedAssetUrls.EnhancedHls) + if err != nil { + fmt.Println("Failed to extract quality from manifest.\n", err) + } } } } @@ -1378,7 +1408,7 @@ func rip(albumId string, token string, storefront string, userToken string) erro "{PlaylistName}", meta.Data[0].Attributes.Name, "{PlaylistId}", albumId, "{Quality}", Quality, - "{Codec}", "ALAC", + "{Codec}", Codec, "{Tag}", Tag_string, ).Replace(config.PlaylistFolderFormat) } else { @@ -1392,7 +1422,7 @@ func rip(albumId string, token string, storefront string, userToken string) erro "{Copyright}", meta.Data[0].Attributes.Copyright, "{AlbumId}", albumId, "{Quality}", Quality, - "{Codec}", "ALAC", + "{Codec}", Codec, "{Tag}", Tag_string, ).Replace(config.AlbumFolderFormat) } @@ -1448,157 +1478,260 @@ func rip(albumId string, token string, storefront string, userToken string) erro } } trackTotal := len(meta.Data[0].Relationships.Tracks.Data) - for trackNum, track := range meta.Data[0].Relationships.Tracks.Data { - trackNum++ - trackTotalnum += 1 - fmt.Printf("Track %d of %d:\n", trackNum, trackTotal) - manifest, err := getInfoFromAdam(track.ID, token, storefront) + arr := make([]int, trackTotal) + for i := 0; i < trackTotal; i++ { + arr[i] = i + 1 + } + selected := []int{} + + if !dl_select { + selected = arr + } else { + + fmt.Print("select: ") + reader := bufio.NewReader(os.Stdin) + input, err := reader.ReadString('\n') if err != nil { - fmt.Println("Failed to get manifest.\n", err) - continue - } - if manifest.Attributes.ExtendedAssetUrls.EnhancedHls == "" { - fmt.Println("Unavailable in ALAC.") - continue - } - EnhancedHls_m3u8, err := checkM3u8(track.ID, "song") - if strings.HasPrefix(EnhancedHls_m3u8, "http") { - manifest.Attributes.ExtendedAssetUrls.EnhancedHls = EnhancedHls_m3u8 + fmt.Println(err) } - var Quality string - if strings.Contains(config.SongFileFormat, "Quality") { - Quality, err = extractMediaQuality(manifest.Attributes.ExtendedAssetUrls.EnhancedHls) + input = strings.TrimSpace(input) + inputs := strings.Fields(input) + + for _, str := range inputs { + num, err := strconv.Atoi(str) if err != nil { - fmt.Println("Failed to extract quality from manifest.\n", err) + fmt.Printf("wrong '%s', skip...\n", str) continue } - } - stringsToJoin := []string{} - if track.Attributes.IsAppleDigitalMaster { - if config.AppleMasterChoice != "" { - stringsToJoin = append(stringsToJoin, config.AppleMasterChoice) - } - } - if track.Attributes.ContentRating == "explicit" { - if config.ExplicitChoice != "" { - stringsToJoin = append(stringsToJoin, config.ExplicitChoice) + + found := false + for i := 0; i < len(arr); i++ { + if arr[i] == num { + selected = append(selected, num) + found = true + break + } } - } - if track.Attributes.ContentRating == "clean" { - if config.CleanChoice != "" { - stringsToJoin = append(stringsToJoin, config.CleanChoice) + + if !found { + fmt.Printf("Option '%d' not found or already selected, skipping...\n", num) } } - Tag_string := strings.Join(stringsToJoin, " ") - songName := strings.NewReplacer( - "{SongId}", track.ID, - "{SongNumer}", fmt.Sprintf("%02d", trackNum), - "{SongName}", track.Attributes.Name, - "{DiscNumber}", fmt.Sprintf("%0d", track.Attributes.DiscNumber), - "{TrackNumber}", fmt.Sprintf("%0d", track.Attributes.TrackNumber), - "{Quality}", Quality, - "{Tag}", Tag_string, - "{Codec}", "ALAC", - ).Replace(config.SongFileFormat) - fmt.Println(songName) - filename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) - lrcFilename := fmt.Sprintf("%s.lrc", forbiddenNames.ReplaceAllString(songName, "_")) - trackPath := filepath.Join(sanAlbumFolder, filename) - var lrc string = "" - if userToken != "your-media-user-token" && (config.EmbedLrc || config.SaveLrcFile) { - ttml, err := getSongLyrics(track.ID, storefront, token, userToken) + fmt.Println("Selected options:", selected) + } + for trackNum, track := range meta.Data[0].Relationships.Tracks.Data { + trackNum++ + if isInArray(selected, trackNum) { + trackTotalnum += 1 + fmt.Printf("Track %d of %d:\n", trackNum, trackTotal) + manifest, err := getInfoFromAdam(track.ID, token, storefront) if err != nil { - fmt.Println("Failed to get lyrics") - } else { - lrc, err = conventTTMLToLRC(ttml) + fmt.Println("Failed to get manifest.\n", err) + continue + } + if manifest.Attributes.ExtendedAssetUrls.EnhancedHls == "" { + fmt.Println("Unavailable.") + continue + } + EnhancedHls_m3u8, err := checkM3u8(track.ID, "song") + if strings.HasPrefix(EnhancedHls_m3u8, "http") { + manifest.Attributes.ExtendedAssetUrls.EnhancedHls = EnhancedHls_m3u8 + } + var Quality string + if strings.Contains(config.SongFileFormat, "Quality") { + if dl_atmos { + Quality = fmt.Sprintf("%dkbps", config.AtmosMax-2000) + } else { + Quality, err = extractMediaQuality(manifest.Attributes.ExtendedAssetUrls.EnhancedHls) + if err != nil { + fmt.Println("Failed to extract quality from manifest.\n", err) + continue + } + } + } + stringsToJoin := []string{} + if track.Attributes.IsAppleDigitalMaster { + if config.AppleMasterChoice != "" { + stringsToJoin = append(stringsToJoin, config.AppleMasterChoice) + } + } + if track.Attributes.ContentRating == "explicit" { + if config.ExplicitChoice != "" { + stringsToJoin = append(stringsToJoin, config.ExplicitChoice) + } + } + if track.Attributes.ContentRating == "clean" { + if config.CleanChoice != "" { + stringsToJoin = append(stringsToJoin, config.CleanChoice) + } + } + Tag_string := strings.Join(stringsToJoin, " ") + + songName := strings.NewReplacer( + "{SongId}", track.ID, + "{SongNumer}", fmt.Sprintf("%02d", trackNum), + "{SongName}", track.Attributes.Name, + "{DiscNumber}", fmt.Sprintf("%0d", track.Attributes.DiscNumber), + "{TrackNumber}", fmt.Sprintf("%0d", track.Attributes.TrackNumber), + "{Quality}", Quality, + "{Tag}", Tag_string, + "{Codec}", Codec, + ).Replace(config.SongFileFormat) + fmt.Println(songName) + filename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) + if dl_atmos { + filename = fmt.Sprintf("%s.ec3", forbiddenNames.ReplaceAllString(songName, "_")) + } + m4afilename := fmt.Sprintf("%s.m4a", forbiddenNames.ReplaceAllString(songName, "_")) + lrcFilename := fmt.Sprintf("%s.lrc", forbiddenNames.ReplaceAllString(songName, "_")) + trackPath := filepath.Join(sanAlbumFolder, filename) + m4atrackPath := filepath.Join(sanAlbumFolder, m4afilename) + var lrc string = "" + if userToken != "your-media-user-token" && (config.EmbedLrc || config.SaveLrcFile) { + ttml, err := getSongLyrics(track.ID, storefront, token, userToken) if err != nil { - fmt.Printf("Failed to parse lyrics: %s \n", err) + fmt.Println("Failed to get lyrics") } else { - if config.SaveLrcFile { - err := writeLyrics(sanAlbumFolder, lrcFilename, lrc) - if err != nil { - fmt.Printf("Failed to write lyrics") - } - if !config.EmbedLrc { - lrc = "" + lrc, err = conventTTMLToLRC(ttml) + if err != nil { + fmt.Printf("Failed to parse lyrics: %s \n", err) + } else { + if config.SaveLrcFile { + err := writeLyrics(sanAlbumFolder, lrcFilename, lrc) + if err != nil { + fmt.Printf("Failed to write lyrics") + } + if !config.EmbedLrc { + lrc = "" + } } } } } - } - exists, err := fileExists(trackPath) - if err != nil { - fmt.Println("Failed to check if track exists.") - } - if exists { - fmt.Println("Track already exists locally.") - oktrackNum += 1 - continue - } + exists, err := fileExists(trackPath) + if err != nil { + fmt.Println("Failed to check if track exists.") + } + if exists { + fmt.Println("Track already exists locally.") + oktrackNum += 1 + continue + } + m4aexists, err := fileExists(m4atrackPath) + if err != nil { + fmt.Println("Failed to check if track exists.") + } + if m4aexists { + fmt.Println("Track already exists locally.") + oktrackNum += 1 + continue + } - trackUrl, keys, err := extractMedia(manifest.Attributes.ExtendedAssetUrls.EnhancedHls) - if err != nil { - fmt.Println("Failed to extract info from manifest.\n", err) - continue - } - info, err := extractSong(trackUrl) - if err != nil { - fmt.Println("Failed to extract track.", err) - continue - } - samplesOk := true - for samplesOk { - for _, i := range info.samples { - if int(i.descIndex) >= len(keys) { - fmt.Println("Decryption size mismatch.") - samplesOk = false + trackUrl, keys, err := extractMedia(manifest.Attributes.ExtendedAssetUrls.EnhancedHls) + if err != nil { + fmt.Println("Failed to extract info from manifest.\n", err) + continue + } + info, err := extractSong(trackUrl) + if err != nil { + fmt.Println("Failed to extract track.", err) + continue + } + samplesOk := true + for samplesOk { + for _, i := range info.samples { + if int(i.descIndex) >= len(keys) { + fmt.Println("Decryption size mismatch.") + samplesOk = false + } } + break } - break - } - if !samplesOk { - continue - } - err = decryptSong(info, keys, meta, trackPath, trackNum, trackTotal) - if err != nil { - fmt.Println("Failed to decrypt track.\n", err) - continue - } - tags := []string{ - fmt.Sprintf("lyrics=%s", lrc), - } - if track.Attributes.ContentRating == "explicit" { - tags = append(tags, "rating=1") - } else if track.Attributes.ContentRating == "clean" { - tags = append(tags, "rating=2") - } else { - tags = append(tags, "rating=0") - } - if config.EmbedCover { - if strings.Contains(albumId, "pl.") && config.DlAlbumcoverForPlaylist { - err = writeCover(sanAlbumFolder, track.ID, track.Attributes.Artwork.URL) - if err != nil { - fmt.Println("Failed to write cover.") + if !samplesOk { + continue + } + err = decryptSong(info, keys, meta, trackPath, trackNum, trackTotal) + if err != nil { + fmt.Println("Failed to decrypt track.\n", err) + continue + } + tags := []string{ + fmt.Sprintf("lyrics=%s", lrc), + } + + index := trackNum - 1 + if dl_atmos { + tags = []string{ + "tool=", + fmt.Sprintf("lyrics=%s", lrc), + fmt.Sprintf("title=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.Name), + fmt.Sprintf("artist=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.ArtistName), + fmt.Sprintf("genre=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.GenreNames[0]), + fmt.Sprintf("created=%s", meta.Data[0].Attributes.ReleaseDate), + fmt.Sprintf("album_artist=%s", meta.Data[0].Attributes.ArtistName), + fmt.Sprintf("composer=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.ComposerName), + fmt.Sprintf("writer=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.ComposerName), + fmt.Sprintf("performer=%s", meta.Data[0].Attributes.ArtistName), + fmt.Sprintf("copyright=%s", meta.Data[0].Attributes.Copyright), + fmt.Sprintf("ISRC=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.Isrc), + fmt.Sprintf("UPC=%s", meta.Data[0].Attributes.Upc), + } + if strings.Contains(albumId, "pl.") && !config.UseSongInfoForPlaylist { + tags = append(tags, "disk=1/1") + tags = append(tags, fmt.Sprintf("track=%s", trackNum)) + tags = append(tags, fmt.Sprintf("tracknum=%d/%d", trackNum, trackTotal)) + tags = append(tags, fmt.Sprintf("album=%s", meta.Data[0].Attributes.Name)) + } else { + tags = append(tags, fmt.Sprintf("disk=%d/%d", meta.Data[0].Relationships.Tracks.Data[index].Attributes.DiscNumber, meta.Data[0].Relationships.Tracks.Data[trackTotal-1].Attributes.DiscNumber)) + tags = append(tags, fmt.Sprintf("track=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.TrackNumber)) + tags = append(tags, fmt.Sprintf("tracknum=%d/%d", meta.Data[0].Relationships.Tracks.Data[index].Attributes.TrackNumber, trackTotal)) + tags = append(tags, fmt.Sprintf("album=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.AlbumName)) } - tags = append(tags, fmt.Sprintf("cover=%s/%s.%s", sanAlbumFolder, track.ID, config.CoverFormat)) + } + if track.Attributes.ContentRating == "explicit" { + tags = append(tags, "rating=1") + } else if track.Attributes.ContentRating == "clean" { + tags = append(tags, "rating=2") } else { - tags = append(tags, fmt.Sprintf("cover=%s/%s.%s", sanAlbumFolder, "cover", config.CoverFormat)) + tags = append(tags, "rating=0") } - } - tagsString := strings.Join(tags, ":") - cmd := exec.Command("MP4Box", "-itags", tagsString, trackPath) - if err := cmd.Run(); err != nil { - fmt.Printf("Embed failed: %v\n", err) - continue - } - if strings.Contains(albumId, "pl.") && config.DlAlbumcoverForPlaylist { - if err := os.Remove(fmt.Sprintf("%s/%s.%s", sanAlbumFolder, track.ID, config.CoverFormat)); err != nil { - fmt.Printf("Error deleting file: %s/%s.%s\n", sanAlbumFolder, track.ID, config.CoverFormat) + if config.EmbedCover { + if strings.Contains(albumId, "pl.") && config.DlAlbumcoverForPlaylist { + err = writeCover(sanAlbumFolder, track.ID, track.Attributes.Artwork.URL) + if err != nil { + fmt.Println("Failed to write cover.") + } + tags = append(tags, fmt.Sprintf("cover=%s/%s.%s", sanAlbumFolder, track.ID, config.CoverFormat)) + } else { + tags = append(tags, fmt.Sprintf("cover=%s/%s.%s", sanAlbumFolder, "cover", config.CoverFormat)) + } + } + tagsString := strings.Join(tags, ":") + cmd := exec.Command("MP4Box", "-itags", tagsString, trackPath) + if dl_atmos { + cmd = exec.Command("MP4Box", "-add", trackPath, "-name", fmt.Sprintf("1=%s", meta.Data[0].Relationships.Tracks.Data[index].Attributes.Name), "-itags", tagsString, "-brand", "mp42", "-ab", "dby1", m4atrackPath) + } + if err := cmd.Run(); err != nil { + fmt.Printf("Embed failed: %v\n", err) continue } + if strings.Contains(albumId, "pl.") && config.DlAlbumcoverForPlaylist { + if err := os.Remove(fmt.Sprintf("%s/%s.%s", sanAlbumFolder, track.ID, config.CoverFormat)); err != nil { + fmt.Printf("Error deleting file: %s/%s.%s\n", sanAlbumFolder, track.ID, config.CoverFormat) + continue + } + } + if dl_atmos { + fmt.Printf("Deleting original EC3 file: %s\n", filepath.Base(trackPath)) + if err := os.Remove(trackPath); err != nil { + fmt.Printf("Error deleting file: %v\n", err) + continue + } + fmt.Printf("Successfully processed and deleted %s\n", filepath.Base(trackPath)) + } + oktrackNum += 1 } - oktrackNum += 1 } return err } @@ -1614,6 +1747,17 @@ func main() { fmt.Println("Failed to get token.") return } + var dlArgs []string + for _, arg := range os.Args { + if strings.Contains(arg, "--atmos") { + dl_atmos = true + } else if strings.Contains(arg, "--select") { + dl_select = true + } else { + dlArgs = append(dlArgs, arg) + } + } + os.Args = dlArgs if strings.Contains(os.Args[1], "/artist/") { newArgs, err := checkArtist(os.Args[1], token) if err != nil { @@ -1882,26 +2026,46 @@ func extractMedia(b string) (string, []string, error) { return master.Variants[i].AverageBandwidth > master.Variants[j].AverageBandwidth }) for _, variant := range master.Variants { - if variant.Codecs == "alac" { - split := strings.Split(variant.Audio, "-") - length := len(split) - length_int, err := strconv.Atoi(split[length-2]) - if err != nil { - return "", nil, err + if dl_atmos { + if variant.Codecs == "ec-3" { + split := strings.Split(variant.Audio, "-") + length := len(split) + length_int, err := strconv.Atoi(split[length-1]) + if err != nil { + return "", nil, err + } + if length_int <= config.AtmosMax { + fmt.Printf("%s\n", variant.Audio) + streamUrlTemp, err := masterUrl.Parse(variant.URI) + if err != nil { + panic(err) + } + streamUrl = streamUrlTemp + break + } } - if length_int <= config.AlacMax { - fmt.Printf("%s-bit / %s Hz\n", split[length-1], split[length-2]) - streamUrlTemp, err := masterUrl.Parse(variant.URI) + } else { + if variant.Codecs == "alac" { + split := strings.Split(variant.Audio, "-") + length := len(split) + length_int, err := strconv.Atoi(split[length-2]) if err != nil { - panic(err) + return "", nil, err + } + if length_int <= config.AlacMax { + fmt.Printf("%s-bit / %s Hz\n", split[length-1], split[length-2]) + streamUrlTemp, err := masterUrl.Parse(variant.URI) + if err != nil { + panic(err) + } + streamUrl = streamUrlTemp + break } - streamUrl = streamUrlTemp - break } } } if streamUrl == nil { - return "", nil, errors.New("no alac codec found") + return "", nil, errors.New("no codec found") } var keys []string keys = append(keys, prefetchKey) @@ -1909,8 +2073,14 @@ func extractMedia(b string) (string, []string, error) { regex := regexp.MustCompile(`"(skd?://[^"]*)"`) matches := regex.FindAllStringSubmatch(masterString, -1) for _, match := range matches { - if strings.HasSuffix(match[1], "c23") || strings.HasSuffix(match[1], "c6") { - keys = append(keys, match[1]) + if dl_atmos { + if strings.HasSuffix(match[1], "c24") || strings.HasSuffix(match[1], "c6") { + keys = append(keys, match[1]) + } + } else { + if strings.HasSuffix(match[1], "c23") || strings.HasSuffix(match[1], "c6") { + keys = append(keys, match[1]) + } } } return streamUrl.String(), keys, nil @@ -1992,23 +2162,30 @@ func extractSong(url string) (*SongInfo, error) { return nil, err } - enca, err := mp4.ExtractBoxWithPayload(f, stbl[0], []mp4.BoxType{ - mp4.BoxTypeStsd(), - mp4.BoxTypeEnca(), - }) - if err != nil { - return nil, err - } - - aalac, err := mp4.ExtractBoxWithPayload(f, &enca[0].Info, - []mp4.BoxType{BoxTypeAlac()}) - if err != nil || len(aalac) != 1 { - return nil, err - } + var extracted *SongInfo + if !dl_atmos { + enca, err := mp4.ExtractBoxWithPayload(f, stbl[0], []mp4.BoxType{ + mp4.BoxTypeStsd(), + mp4.BoxTypeEnca(), + }) + if err != nil { + return nil, err + } - extracted := &SongInfo{ - r: f, - alacParam: aalac[0].Payload.(*Alac), + aalac, err := mp4.ExtractBoxWithPayload(f, &enca[0].Info, + []mp4.BoxType{BoxTypeAlac()}) + if err != nil || len(aalac) != 1 { + return nil, err + } + extracted = &SongInfo{ + r: f, + alacParam: aalac[0].Payload.(*Alac), + } + } else { + extracted = &SongInfo{ + r: f, + // alacParam: aalac[0].Payload.(*Alac), + } } moofs, err := mp4.ExtractBox(f, nil, []mp4.BoxType{