Compare commits
19 Commits
a4c7db8195
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a62f5156f0 | |||
| 747343162b | |||
| 676641d5f9 | |||
| 96dc36f112 | |||
|
54da5b7a35
|
|||
|
4d0622073a
|
|||
| 49e554931e | |||
| 2814a23874 | |||
| 3a48a5d667 | |||
| 5cb53dff3b | |||
| b3258662f6 | |||
|
1765813f08
|
|||
|
c11fbf88db
|
|||
|
88314554d0
|
|||
|
686bfc79bf
|
|||
| 300a412058 | |||
|
609bfd03cc
|
|||
|
5862d7a8d8
|
|||
|
be81c22e49
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018-present TaurusXin and contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
24
README.md
24
README.md
@@ -2,7 +2,25 @@
|
|||||||
|
|
||||||
基于 https://github.com/taurusxin/ncmdump 的 Golang 移植版
|
基于 https://github.com/taurusxin/ncmdump 的 Golang 移植版
|
||||||
|
|
||||||
支持网易云音乐最新的 3.x 版本,但需要注意:从该版本开始网易云音乐不再在 ncm 文件中内置封面图片,本工具支持从网易服务器上自动下载对应歌曲的封面图并写入到最终的音乐文件中
|
支持网易云音乐最新的 3.x 版本,但需要注意:从 3. x开始的某些网易云音乐版本不再在 ncm 文件中内置封面图片,本项目支持从网易服务器上自动下载对应歌曲的封面图并写入到最终的音乐文件中
|
||||||
|
|
||||||
|
你也可以去 https://git.taurusxin.com/taurusxin/ncmdump-gui 下载基于本项目的 gui 可视化图形应用,只需简单点击即可自动转换。
|
||||||
|
|
||||||
|
## 如何提 Issue
|
||||||
|
|
||||||
|
由于本站恶意机器人注册过多,已关闭账号注册,如果需要提 Issue 请前往 [GitHub](https://github.com/taurusxin/ncmdump),必须注明 Issue 的主题为 ncmdump-go,敬请谅解。
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
你可以使用去 [releases](https://git.taurusxin.com/taurusxin/ncmdump-go/releases/latest) 下载最新版预编译好的二进制文件,或者你也可以用包管理器来安装
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Windows Scoop
|
||||||
|
scoop bucket add taurusxin https://git.taurusxin.com/taurusxin/scoop-bucket.git # 添加 scoop 源
|
||||||
|
scoop install ncmdump-go # 安装 ncmdump-go
|
||||||
|
|
||||||
|
# macOS & Linux 之后会支持
|
||||||
|
```
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
@@ -54,7 +72,7 @@ ncmdump-go -d source_dir -o output_dir -r
|
|||||||
使用 go module 下载 ncmdump-go 包
|
使用 go module 下载 ncmdump-go 包
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
go get -u github.com/taurusxin/ncmdump-go
|
go get -u git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
```
|
```
|
||||||
|
|
||||||
导入并使用
|
导入并使用
|
||||||
@@ -64,7 +82,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/taurusxin/ncmdump-go/ncmcrypt"
|
"git.taurusxin.com/taurusxin/ncmdump-go/ncmcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
12
build.sh
12
build.sh
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
VERSION=1.6.0
|
VERSION=1.7.5
|
||||||
|
|
||||||
# Clean up the build directory
|
# Clean up the build directory
|
||||||
rm -rf build
|
rm -rf build
|
||||||
@@ -8,30 +8,30 @@ mkdir build
|
|||||||
|
|
||||||
# Linux amd64
|
# Linux amd64
|
||||||
echo "Building for Linux amd64..."
|
echo "Building for Linux amd64..."
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go github.com/taurusxin/ncmdump-go
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
tar zcf build/ncmdump-go_linux_amd64_$VERSION.tar.gz -C build ncmdump-go
|
tar zcf build/ncmdump-go_linux_amd64_$VERSION.tar.gz -C build ncmdump-go
|
||||||
rm build/ncmdump-go
|
rm build/ncmdump-go
|
||||||
|
|
||||||
# Linux arm64
|
# Linux arm64
|
||||||
echo "Building for Linux arm64..."
|
echo "Building for Linux arm64..."
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o build/ncmdump-go github.com/taurusxin/ncmdump-go
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -o build/ncmdump-go git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
tar zcf build/ncmdump-go_linux_arm64_$VERSION.tar.gz -C build ncmdump-go
|
tar zcf build/ncmdump-go_linux_arm64_$VERSION.tar.gz -C build ncmdump-go
|
||||||
rm build/ncmdump-go
|
rm build/ncmdump-go
|
||||||
|
|
||||||
# macOS amd64
|
# macOS amd64
|
||||||
echo "Building for macOS amd64..."
|
echo "Building for macOS amd64..."
|
||||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go github.com/taurusxin/ncmdump-go
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
tar zcf build/ncmdump-go_darwin_amd64_$VERSION.tar.gz -C build ncmdump-go
|
tar zcf build/ncmdump-go_darwin_amd64_$VERSION.tar.gz -C build ncmdump-go
|
||||||
rm build/ncmdump-go
|
rm build/ncmdump-go
|
||||||
|
|
||||||
# macOS arm64
|
# macOS arm64
|
||||||
echo "Building for macOS arm64..."
|
echo "Building for macOS arm64..."
|
||||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-w -s" -o build/ncmdump-go github.com/taurusxin/ncmdump-go
|
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-w -s" -o build/ncmdump-go git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
tar zcf build/ncmdump-go_darwin_arm64_$VERSION.tar.gz -C build ncmdump-go
|
tar zcf build/ncmdump-go_darwin_arm64_$VERSION.tar.gz -C build ncmdump-go
|
||||||
rm build/ncmdump-go
|
rm build/ncmdump-go
|
||||||
|
|
||||||
# Windows amd64
|
# Windows amd64
|
||||||
echo "Building for Windows amd64..."
|
echo "Building for Windows amd64..."
|
||||||
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go.exe github.com/taurusxin/ncmdump-go
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-w -s" -o build/ncmdump-go.exe git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
zip -q -j build/ncmdump-go_windows_amd64_$VERSION.zip ./build/ncmdump-go.exe
|
zip -q -j build/ncmdump-go_windows_amd64_$VERSION.zip ./build/ncmdump-go.exe
|
||||||
rm build/ncmdump-go.exe
|
rm build/ncmdump-go.exe
|
||||||
3
go.mod
3
go.mod
@@ -1,4 +1,4 @@
|
|||||||
module github.com/taurusxin/ncmdump-go
|
module git.taurusxin.com/taurusxin/ncmdump-go
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ require github.com/bogem/id3v2/v2 v2.1.4
|
|||||||
require (
|
require (
|
||||||
github.com/TwiN/go-color v1.4.1
|
github.com/TwiN/go-color v1.4.1
|
||||||
github.com/go-flac/flacpicture v0.3.0
|
github.com/go-flac/flacpicture v0.3.0
|
||||||
|
github.com/go-flac/flacvorbis v0.2.0
|
||||||
github.com/go-flac/go-flac v1.0.0
|
github.com/go-flac/go-flac v1.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -4,6 +4,8 @@ github.com/bogem/id3v2/v2 v2.1.4 h1:CEwe+lS2p6dd9UZRlPc1zbFNIha2mb2qzT1cCEoNWoI=
|
|||||||
github.com/bogem/id3v2/v2 v2.1.4/go.mod h1:l+gR8MZ6rc9ryPTPkX77smS5Me/36gxkMgDayZ9G1vY=
|
github.com/bogem/id3v2/v2 v2.1.4/go.mod h1:l+gR8MZ6rc9ryPTPkX77smS5Me/36gxkMgDayZ9G1vY=
|
||||||
github.com/go-flac/flacpicture v0.3.0 h1:LkmTxzFLIynwfhHiZsX0s8xcr3/u33MzvV89u+zOT8I=
|
github.com/go-flac/flacpicture v0.3.0 h1:LkmTxzFLIynwfhHiZsX0s8xcr3/u33MzvV89u+zOT8I=
|
||||||
github.com/go-flac/flacpicture v0.3.0/go.mod h1:DPbrzVYQ3fJcvSgLFp9HXIrEQEdfdk/+m0nQCzwodZI=
|
github.com/go-flac/flacpicture v0.3.0/go.mod h1:DPbrzVYQ3fJcvSgLFp9HXIrEQEdfdk/+m0nQCzwodZI=
|
||||||
|
github.com/go-flac/flacvorbis v0.2.0 h1:KH0xjpkNTXFER4cszH4zeJxYcrHbUobz/RticWGOESs=
|
||||||
|
github.com/go-flac/flacvorbis v0.2.0/go.mod h1:uIysHOtuU7OLGoCRG92bvnkg7QEqHx19qKRV6K1pBrI=
|
||||||
github.com/go-flac/go-flac v1.0.0 h1:6qI9XOVLcO50xpzm3nXvO31BgDgHhnr/p/rER/K/doY=
|
github.com/go-flac/go-flac v1.0.0 h1:6qI9XOVLcO50xpzm3nXvO31BgDgHhnr/p/rER/K/doY=
|
||||||
github.com/go-flac/go-flac v1.0.0/go.mod h1:WnZhcpmq4u1UdZMNn9LYSoASpWOCMOoxXxcWEHSzkW8=
|
github.com/go-flac/go-flac v1.0.0/go.mod h1:WnZhcpmq4u1UdZMNn9LYSoASpWOCMOoxXxcWEHSzkW8=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
|||||||
6
main.go
6
main.go
@@ -2,8 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/taurusxin/ncmdump-go/ncmcrypt"
|
"git.taurusxin.com/taurusxin/ncmdump-go/ncmcrypt"
|
||||||
"github.com/taurusxin/ncmdump-go/utils"
|
"git.taurusxin.com/taurusxin/ncmdump-go/utils"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if *showVersion {
|
if *showVersion {
|
||||||
fmt.Println("ncmdump version 1.6.0")
|
fmt.Println("ncmdump version 1.7.5")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func NewNeteaseCloudMusicMetadata(meta string) *NeteaseClousMusicMetadata {
|
|||||||
if len(artists) > 0 {
|
if len(artists) > 0 {
|
||||||
for i, artist := range artists {
|
for i, artist := range artists {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
metaData.mArtist += "/"
|
metaData.mArtist += " / "
|
||||||
}
|
}
|
||||||
metaData.mArtist += artist.Array()[0].String()
|
metaData.mArtist += artist.Array()[0].String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,16 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/bogem/id3v2/v2"
|
|
||||||
"github.com/go-flac/flacpicture"
|
|
||||||
"github.com/go-flac/go-flac"
|
|
||||||
"github.com/taurusxin/ncmdump-go/utils"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"git.taurusxin.com/taurusxin/ncmdump-go/utils"
|
||||||
|
"github.com/bogem/id3v2/v2"
|
||||||
|
"github.com/go-flac/flacpicture"
|
||||||
|
"github.com/go-flac/flacvorbis"
|
||||||
|
"github.com/go-flac/go-flac"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NcmFormat = string
|
type NcmFormat = string
|
||||||
@@ -151,7 +153,7 @@ func (ncm *NeteaseCloudMusic) Dump(targetDir string) (bool, error) {
|
|||||||
outputStream = output
|
outputStream = output
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.Write(buffer)
|
outputStream.Write(buffer[:n])
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.Close()
|
outputStream.Close()
|
||||||
@@ -178,12 +180,14 @@ func (ncm *NeteaseCloudMusic) FixMetadata(fetchAlbumImageFromRemote bool) (bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ncm.mFormat == Mp3 {
|
switch ncm.mFormat {
|
||||||
|
case Mp3:
|
||||||
audioFile, err := id3v2.Open(ncm.mDumpFilePath, id3v2.Options{Parse: true})
|
audioFile, err := id3v2.Open(ncm.mDumpFilePath, id3v2.Options{Parse: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
defer audioFile.Close()
|
defer audioFile.Close()
|
||||||
|
audioFile.SetDefaultEncoding(id3v2.EncodingUTF8)
|
||||||
audioFile.SetTitle(ncm.mMetadata.mName)
|
audioFile.SetTitle(ncm.mMetadata.mName)
|
||||||
audioFile.SetArtist(ncm.mMetadata.mArtist)
|
audioFile.SetArtist(ncm.mMetadata.mArtist)
|
||||||
audioFile.SetAlbum(ncm.mMetadata.mAlbum)
|
audioFile.SetAlbum(ncm.mMetadata.mAlbum)
|
||||||
@@ -203,7 +207,7 @@ func (ncm *NeteaseCloudMusic) FixMetadata(fetchAlbumImageFromRemote bool) (bool,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
} else if ncm.mFormat == Flac {
|
case Flac:
|
||||||
audioFile, err := flac.ParseFile(ncm.mDumpFilePath)
|
audioFile, err := flac.ParseFile(ncm.mDumpFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -217,12 +221,43 @@ func (ncm *NeteaseCloudMusic) FixMetadata(fetchAlbumImageFromRemote bool) (bool,
|
|||||||
pictureMeta := pic.Marshal()
|
pictureMeta := pic.Marshal()
|
||||||
audioFile.Meta = append(audioFile.Meta, &pictureMeta)
|
audioFile.Meta = append(audioFile.Meta, &pictureMeta)
|
||||||
}
|
}
|
||||||
generalMeta := &flac.MetaDataBlock{
|
|
||||||
Type: flac.VorbisComment,
|
var cmts *flacvorbis.MetaDataBlockVorbisComment
|
||||||
Data: []byte(fmt.Sprintf("title=%s\nartist=%s\nalbum=%s", ncm.mMetadata.mName, ncm.mMetadata.mArtist, ncm.mMetadata.mAlbum)),
|
var cmtIdx int
|
||||||
|
for idx, meta := range audioFile.Meta {
|
||||||
|
if meta.Type == flac.VorbisComment {
|
||||||
|
cmts, err = flacvorbis.ParseFromMetaDataBlock(*meta)
|
||||||
|
cmtIdx = idx
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
audioFile.Meta = append(audioFile.Meta, generalMeta)
|
if cmts == nil && cmtIdx > 0 {
|
||||||
|
cmts = flacvorbis.New()
|
||||||
|
}
|
||||||
|
|
||||||
|
// flac 可能自带元数据 当且仅当没有该项时才向目标添加元数据
|
||||||
|
if res, _ := cmts.Get(flacvorbis.FIELD_TITLE); len(res) == 0 {
|
||||||
|
_ = cmts.Add(flacvorbis.FIELD_TITLE, ncm.mMetadata.mName)
|
||||||
|
}
|
||||||
|
if res, _ := cmts.Get(flacvorbis.FIELD_ARTIST); len(res) == 0 {
|
||||||
|
_ = cmts.Add(flacvorbis.FIELD_ARTIST, ncm.mMetadata.mArtist)
|
||||||
|
}
|
||||||
|
if res, _ := cmts.Get(flacvorbis.FIELD_ALBUM); len(res) == 0 {
|
||||||
|
_ = cmts.Add(flacvorbis.FIELD_ALBUM, ncm.mMetadata.mAlbum)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmtsmeta := cmts.Marshal()
|
||||||
|
|
||||||
|
if cmtIdx > 0 {
|
||||||
|
audioFile.Meta[cmtIdx] = &cmtsmeta
|
||||||
|
} else {
|
||||||
|
audioFile.Meta = append(audioFile.Meta, &cmtsmeta)
|
||||||
|
}
|
||||||
|
|
||||||
err = audioFile.Save(ncm.mDumpFilePath)
|
err = audioFile.Save(ncm.mDumpFilePath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user