From 013f70d22036699b665aab8612aff8651769a3aa Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:01:43 +0800 Subject: [PATCH 1/6] add animated artwork download --- main.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index cb9deee..635a32c 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ var ( type Config struct { MediaUserToken string `yaml:"media-user-token"` SaveLrcFile bool `yaml:"save-lrc-file"` + SaveAnimatedArtwork bool `yaml:"save-animated-artwork"` EmbedLrc bool `yaml:"embed-lrc"` EmbedCover bool `yaml:"embed-cover"` CoverSize string `yaml:"cover-size"` @@ -1153,6 +1154,7 @@ func getMeta(albumId string, token string, storefront string) (*AutoGenerated, e query.Set("fields[artists]", "name") query.Set("fields[albums:albums]", "artistName,artwork,name,releaseDate,url") query.Set("fields[record-labels]", "name") + query.Set("extend", "editorialVideo") // query.Set("l", "en-gb") req.URL.RawQuery = query.Encode() do, err := http.DefaultClient.Do(req) @@ -1389,6 +1391,25 @@ func rip(albumId string, token string, storefront string, userToken string) erro if err != nil { fmt.Println("Failed to write cover.") } + //get animated artwork + if Config.SaveAnimatedArtwork && meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video != "" { + motionvideoUrl, err := extractVideo(meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video) + if err != nil { + fmt.Println("no motion video.\n", err) + } + exists, err := fileExists(filepath.Join(sanAlbumFolder, "animated_artwork.mp4")) + if err != nil { + fmt.Println("Failed to check if animated artwork exists.") + } + if exists { + fmt.Println("Animated artwork already exists locally.") + } else { + cmd := exec.Command("ffmpeg", "-loglevel", "quiet", "-y", "-i", motionvideoUrl, "-c", "copy", filepath.Join(sanAlbumFolder, "animated_artwork.mp4")) + if err := cmd.Run(); err != nil { + fmt.Printf("animated artwork dl err: %v\n", err) + } + } + } trackTotal := len(meta.Data[0].Relationships.Tracks.Data) for trackNum, track := range meta.Data[0].Relationships.Tracks.Data { trackNum++ @@ -1857,7 +1878,45 @@ func extractMedia(b string) (string, []string, error) { } return streamUrl.String(), keys, nil } - +func extractVideo(c string) (string, error) { + MediaUrl, err := url.Parse(c) + 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 + 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) + if err != nil { + return "", err + } + } + if streamUrl == nil { + return "", errors.New("no video codec found") + } + return streamUrl.String(), nil +} func extractSong(url string) (*SongInfo, error) { fmt.Println("Downloading...") track, err := http.Get(url) @@ -2307,6 +2366,14 @@ type AutoGenerated struct { Kind string `json:"kind"` } `json:"playParams"` IsCompilation bool `json:"isCompilation"` + EditorialVideo struct { + MotionDetailSquare struct { + Video string `json:"video"` + } `json:"motionDetailSquare"` + MotionSquareVideo1x1 struct { + Video string `json:"video"` + } `json:"motionSquareVideo1x1"` + } `json:"editorialVideo"` } `json:"attributes"` Relationships struct { RecordLabels struct { From 9f4636598c5037d7a2dc31faf2284bae388e78f9 Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:03:22 +0800 Subject: [PATCH 2/6] add save-animated-artwork --- config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/config.yaml b/config.yaml index fafb239..1587c27 100644 --- a/config.yaml +++ b/config.yaml @@ -1,6 +1,7 @@ media-user-token: "your-media-user-token" embed-lrc: true save-lrc-file: false +save-animated-artwork: false embed-cover: true cover-size: 5000x5000 cover-format: jpg #jpg or png From 4fba1ee0bcebe2f3522d57999c8d191e759c2805 Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:34:55 +0800 Subject: [PATCH 3/6] fix Config to config --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 635a32c..8730f1e 100644 --- a/main.go +++ b/main.go @@ -1392,7 +1392,7 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Println("Failed to write cover.") } //get animated artwork - if Config.SaveAnimatedArtwork && meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video != "" { + if config.SaveAnimatedArtwork && meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video != "" { motionvideoUrl, err := extractVideo(meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video) if err != nil { fmt.Println("no motion video.\n", err) From 21925437c16b5f77e07bc5ef54678b0341479b8e Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:58:27 +0800 Subject: [PATCH 4/6] fix playlist animated artwork --- main.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 8730f1e..dc5e85b 100644 --- a/main.go +++ b/main.go @@ -1392,8 +1392,9 @@ func rip(albumId string, token string, storefront string, userToken string) erro fmt.Println("Failed to write cover.") } //get animated artwork - if config.SaveAnimatedArtwork && meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video != "" { - motionvideoUrl, err := extractVideo(meta.Data[0].Attributes.EditorialVideo.MotionSquareVideo1x1.Video) + if config.SaveAnimatedArtwork && meta.Data[0].Attributes.EditorialVideo.MotionDetailSquare.Video != "" { + fmt.Println("Found Animation Artwork.") + motionvideoUrl, err := extractVideo(meta.Data[0].Attributes.EditorialVideo.MotionDetailSquare.Video) if err != nil { fmt.Println("no motion video.\n", err) } From e7f2986988f8e3792a95664dcc618b788b22b891 Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:37:37 +0800 Subject: [PATCH 5/6] add animated artwork for emby --- main.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/main.go b/main.go index dc5e85b..cca75d6 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,7 @@ type Config struct { MediaUserToken string `yaml:"media-user-token"` SaveLrcFile bool `yaml:"save-lrc-file"` SaveAnimatedArtwork bool `yaml:"save-animated-artwork"` + EmbyAnimatedArtwork bool `yaml:"emby-animated-artwork"` EmbedLrc bool `yaml:"embed-lrc"` EmbedCover bool `yaml:"embed-cover"` CoverSize string `yaml:"cover-size"` @@ -1405,10 +1406,20 @@ func rip(albumId string, token string, storefront string, userToken string) erro if exists { fmt.Println("Animated artwork already exists locally.") } else { + fmt.Println("Animation Artwork Downloading...") cmd := exec.Command("ffmpeg", "-loglevel", "quiet", "-y", "-i", motionvideoUrl, "-c", "copy", filepath.Join(sanAlbumFolder, "animated_artwork.mp4")) if err := cmd.Run(); err != nil { fmt.Printf("animated artwork dl err: %v\n", err) + } else { + fmt.Println("Animation Artwork Downloaded") + } + if config.EmbyAnimatedArtwork { + cmd2 := exec.Command("ffmpeg", "-i", filepath.Join(sanAlbumFolder, "animated_artwork.mp4"), "-vf", "scale=440:-1", "-r", "24", "-f", "gif", filepath.Join(sanAlbumFolder, "folder.jpg")) + if err := cmd2.Run(); err != nil { + fmt.Printf("animated artwork to gif err: %v\n", err) + } } + } } trackTotal := len(meta.Data[0].Relationships.Tracks.Data) From a7e11e7beb595efa56354215d7ef79296ce9c71d Mon Sep 17 00:00:00 2001 From: itouakirai <85016486+itouakirai@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:45:15 +0800 Subject: [PATCH 6/6] add emby animated artwork config --- config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.yaml b/config.yaml index 1587c27..990e328 100644 --- a/config.yaml +++ b/config.yaml @@ -1,7 +1,8 @@ media-user-token: "your-media-user-token" embed-lrc: true save-lrc-file: false -save-animated-artwork: false +save-animated-artwork: false # If enabled, requires ffmpeg +emby-animated-artwork: false # If enabled, requires ffmpeg embed-cover: true cover-size: 5000x5000 cover-format: jpg #jpg or png