Merge branch 'master' into fix/UppercaseRepoName

This commit is contained in:
Andre Wei 2024-10-21 13:17:24 +08:00 committed by GitHub
commit 5c1a21da24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 57 additions and 52 deletions

View File

@ -115,7 +115,7 @@ docker-platforms: ##@Cross_Compilation List supported platforms
.PHONY: docker-platforms
docker-build: ##@Cross_Compilation Cross-compile for any supported platform (check `make docker-platforms`)
docker build \
docker buildx build \
--platform $(PLATFORMS) \
--build-arg GIT_TAG=${GIT_TAG} \
--build-arg GIT_SHA=${GIT_SHA} \
@ -127,7 +127,7 @@ docker-image: ##@Cross_Compilation Build Docker image, tagged as `deluan/navidro
@echo $(IMAGE_PLATFORMS) | grep -q "windows" && echo "ERROR: Windows is not supported for Docker builds" && exit 1 || true
@echo $(IMAGE_PLATFORMS) | grep -q "darwin" && echo "ERROR: macOS is not supported for Docker builds" && exit 1 || true
@echo $(IMAGE_PLATFORMS) | grep -q "arm/v5" && echo "ERROR: Linux ARMv5 is not supported for Docker builds" && exit 1 || true
docker build \
docker buildx build \
--platform $(IMAGE_PLATFORMS) \
--build-arg GIT_TAG=${GIT_TAG} \
--build-arg GIT_SHA=${GIT_SHA} \

View File

@ -18,8 +18,6 @@ import (
type FFmpeg interface {
Transcode(ctx context.Context, command, path string, maxBitRate, offset int) (io.ReadCloser, error)
ExtractImage(ctx context.Context, path string) (io.ReadCloser, error)
ConvertToWAV(ctx context.Context, path string) (io.ReadCloser, error)
ConvertToFLAC(ctx context.Context, path string) (io.ReadCloser, error)
Probe(ctx context.Context, files []string) (string, error)
CmdPath() (string, error)
IsAvailable() bool
@ -33,8 +31,6 @@ func New() FFmpeg {
const (
extractImageCmd = "ffmpeg -i %s -an -vcodec copy -f image2pipe -"
probeCmd = "ffmpeg %s -f ffmetadata"
createWavCmd = "ffmpeg -i %s -c:a pcm_s16le -f wav -"
createFLACCmd = "ffmpeg -i %s -f flac -"
)
type ffmpeg struct{}
@ -55,16 +51,6 @@ func (e *ffmpeg) ExtractImage(ctx context.Context, path string) (io.ReadCloser,
return e.start(ctx, args)
}
func (e *ffmpeg) ConvertToWAV(ctx context.Context, path string) (io.ReadCloser, error) {
args := createFFmpegCommand(createWavCmd, path, 0, 0)
return e.start(ctx, args)
}
func (e *ffmpeg) ConvertToFLAC(ctx context.Context, path string) (io.ReadCloser, error) {
args := createFFmpegCommand(createFLACCmd, path, 0, 0)
return e.start(ctx, args)
}
func (e *ffmpeg) Probe(ctx context.Context, files []string) (string, error) {
if _, err := ffmpegCmd(); err != nil {
return "", err
@ -153,31 +139,26 @@ func (j *ffCmd) wait() {
// Path will always be an absolute path
func createFFmpegCommand(cmd, path string, maxBitRate, offset int) []string {
split := strings.Split(fixCmd(cmd), " ")
var parts []string
for _, s := range split {
var args []string
for _, s := range fixCmd(cmd) {
if strings.Contains(s, "%s") {
s = strings.ReplaceAll(s, "%s", path)
parts = append(parts, s)
args = append(args, s)
if offset > 0 && !strings.Contains(cmd, "%t") {
parts = append(parts, "-ss", strconv.Itoa(offset))
args = append(args, "-ss", strconv.Itoa(offset))
}
} else {
s = strings.ReplaceAll(s, "%t", strconv.Itoa(offset))
s = strings.ReplaceAll(s, "%b", strconv.Itoa(maxBitRate))
parts = append(parts, s)
args = append(args, s)
}
}
return parts
return args
}
func createProbeCommand(cmd string, inputs []string) []string {
split := strings.Split(fixCmd(cmd), " ")
var args []string
for _, s := range split {
for _, s := range fixCmd(cmd) {
if s == "%s" {
for _, inp := range inputs {
args = append(args, "-i", inp)
@ -189,18 +170,15 @@ func createProbeCommand(cmd string, inputs []string) []string {
return args
}
func fixCmd(cmd string) string {
split := strings.Split(cmd, " ")
var result []string
func fixCmd(cmd string) []string {
split := strings.Fields(cmd)
cmdPath, _ := ffmpegCmd()
for _, s := range split {
for i, s := range split {
if s == "ffmpeg" || s == "ffmpeg.exe" {
result = append(result, cmdPath)
} else {
result = append(result, s)
split[i] = cmdPath
}
}
return strings.Join(result, " ")
return split
}
func ffmpegCmd() (string, error) {
@ -223,6 +201,7 @@ func ffmpegCmd() (string, error) {
return ffmpegPath, ffmpegErr
}
// These variables are accessible here for tests. Do not use them directly in production code. Use ffmpegCmd() instead.
var (
ffOnce sync.Once
ffmpegPath string

View File

@ -27,6 +27,10 @@ var _ = Describe("ffmpeg", func() {
args := createFFmpegCommand("ffmpeg -i %s -b:a %bk mp3 -", "/music library/file.mp3", 123, 0)
Expect(args).To(Equal([]string{"ffmpeg", "-i", "/music library/file.mp3", "-b:a", "123k", "mp3", "-"}))
})
It("handles extra spaces in the command string", func() {
args := createFFmpegCommand("ffmpeg -i %s -b:a %bk mp3 -", "/music library/file.mp3", 123, 0)
Expect(args).To(Equal([]string{"ffmpeg", "-i", "/music library/file.mp3", "-b:a", "123k", "mp3", "-"}))
})
Context("when command has time offset param", func() {
It("creates a valid command line with offset", func() {
args := createFFmpegCommand("ffmpeg -i %s -b:a %bk -ss %t mp3 -", "/music library/file.mp3", 123, 456)
@ -48,4 +52,17 @@ var _ = Describe("ffmpeg", func() {
Expect(args).To(Equal([]string{"ffmpeg", "-i", "/music library/one.mp3", "-i", "/music library/two.mp3", "-f", "ffmetadata"}))
})
})
When("ffmpegPath is set", func() {
It("returns the correct ffmpeg path", func() {
ffmpegPath = "/usr/bin/ffmpeg"
args := createProbeCommand(probeCmd, []string{"one.mp3"})
Expect(args).To(Equal([]string{"/usr/bin/ffmpeg", "-i", "one.mp3", "-f", "ffmetadata"}))
})
It("returns the correct ffmpeg path with spaces", func() {
ffmpegPath = "/usr/bin/with spaces/ffmpeg.exe"
args := createProbeCommand(probeCmd, []string{"one.mp3"})
Expect(args).To(Equal([]string{"/usr/bin/with spaces/ffmpeg.exe", "-i", "one.mp3", "-f", "ffmetadata"}))
})
})
})

View File

@ -162,10 +162,10 @@ func (s *playlists) parseM3U(ctx context.Context, pls *model.Playlist, baseDir s
}
existing := make(map[string]int, len(found))
for idx := range found {
existing[found[idx].Path] = idx
existing[strings.ToLower(found[idx].Path)] = idx
}
for _, path := range filteredLines {
idx, ok := existing[path]
idx, ok := existing[strings.ToLower(path)]
if ok {
mfs = append(mfs, found[idx])
} else {

View File

@ -142,6 +142,20 @@ var _ = Describe("Playlists", func() {
Expect(pls.Tracks[1].Path).To(Equal("test1.mp3"))
Expect(pls.Tracks[2].Path).To(Equal("test2.mp3"))
})
It("is case-insensitive when comparing paths", func() {
repo.data = []string{
"tEsT1.Mp3",
}
m3u := strings.Join([]string{
"TeSt1.mP3",
}, "\n")
f := strings.NewReader(m3u)
pls, err := ps.ImportM3U(ctx, f)
Expect(err).ToNot(HaveOccurred())
Expect(pls.Tracks).To(HaveLen(1))
Expect(pls.Tracks[0].Path).To(Equal("tEsT1.Mp3"))
})
})
})

View File

@ -0,0 +1,9 @@
-- +goose Up
create index if not exists media_file_sort_title on media_file(coalesce(nullif(sort_title,''),order_title));
create index if not exists album_sort_name on album(coalesce(nullif(sort_album_name,''),order_album_name));
create index if not exists artist_sort_name on artist(coalesce(nullif(sort_artist_name,''),order_artist_name));
-- +goose Down
drop index if exists media_file_sort_title;
drop index if exists album_sort_name;
drop index if exists artist_sort_name;

View File

@ -37,20 +37,6 @@ func (ff *MockFFmpeg) ExtractImage(context.Context, string) (io.ReadCloser, erro
return ff, nil
}
func (ff *MockFFmpeg) ConvertToFLAC(context.Context, string) (io.ReadCloser, error) {
if ff.Error != nil {
return nil, ff.Error
}
return ff, nil
}
func (ff *MockFFmpeg) ConvertToWAV(context.Context, string) (io.ReadCloser, error) {
if ff.Error != nil {
return nil, ff.Error
}
return ff, nil
}
func (ff *MockFFmpeg) Probe(context.Context, []string) (string, error) {
if ff.Error != nil {
return "", ff.Error