mirror of
https://github.com/navidrome/navidrome.git
synced 2025-04-14 11:17:19 +03:00
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package engine
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/deluan/navidrome/conf"
|
|
"github.com/deluan/navidrome/log"
|
|
"github.com/deluan/navidrome/model"
|
|
"github.com/deluan/navidrome/persistence"
|
|
"github.com/djherbis/fscache"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("MediaStreamer", func() {
|
|
var streamer MediaStreamer
|
|
var ds model.DataStore
|
|
var cache fscache.Cache
|
|
var tempDir string
|
|
ffmpeg := &fakeFFmpeg{Data: "fake data"}
|
|
ctx := log.NewContext(nil)
|
|
|
|
BeforeSuite(func() {
|
|
tempDir, _ = ioutil.TempDir("", "stream_tests")
|
|
fs, _ := fscache.NewFs(tempDir, 0755)
|
|
cache, _ = fscache.NewCache(fs, nil)
|
|
})
|
|
|
|
BeforeEach(func() {
|
|
conf.Server.EnableDownsampling = true
|
|
ds = &persistence.MockDataStore{}
|
|
ds.MediaFile(ctx).(*persistence.MockMediaFile).SetData(`[{"id": "123", "path": "tests/fixtures/test.mp3", "bitRate": 128, "duration": 257.0}]`, 1)
|
|
streamer = NewMediaStreamer(ds, ffmpeg, cache)
|
|
})
|
|
|
|
AfterSuite(func() {
|
|
os.RemoveAll(tempDir)
|
|
})
|
|
|
|
Context("NewStream", func() {
|
|
It("returns a seekable stream if format is 'raw'", func() {
|
|
s, err := streamer.NewStream(ctx, "123", 0, "raw")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(s.Seekable()).To(BeTrue())
|
|
})
|
|
It("returns a seekable stream if maxBitRate is 0", func() {
|
|
s, err := streamer.NewStream(ctx, "123", 0, "mp3")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(s.Seekable()).To(BeTrue())
|
|
})
|
|
It("returns a seekable stream if maxBitRate is higher than file bitRate", func() {
|
|
s, err := streamer.NewStream(ctx, "123", 320, "mp3")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(s.Seekable()).To(BeTrue())
|
|
})
|
|
It("returns a NON seekable stream if transcode is required", func() {
|
|
s, err := streamer.NewStream(ctx, "123", 64, "mp3")
|
|
Expect(err).To(BeNil())
|
|
Expect(s.Seekable()).To(BeFalse())
|
|
Expect(s.Duration()).To(Equal(float32(257.0)))
|
|
})
|
|
It("returns a seekable stream if the file is complete in the cache", func() {
|
|
Eventually(func() bool { return ffmpeg.closed }).Should(BeTrue())
|
|
s, err := streamer.NewStream(ctx, "123", 64, "mp3")
|
|
Expect(err).To(BeNil())
|
|
Expect(s.Seekable()).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
|
|
type fakeFFmpeg struct {
|
|
Data string
|
|
r io.Reader
|
|
closed bool
|
|
}
|
|
|
|
func (ff *fakeFFmpeg) Start(ctx context.Context, path string, maxBitRate int, format string) (f io.ReadCloser, err error) {
|
|
ff.r = strings.NewReader(ff.Data)
|
|
return ff, nil
|
|
}
|
|
|
|
func (ff *fakeFFmpeg) Read(p []byte) (n int, err error) {
|
|
return ff.r.Read(p)
|
|
}
|
|
|
|
func (ff *fakeFFmpeg) Close() error {
|
|
ff.closed = true
|
|
return nil
|
|
}
|