switch back to using HTTP server to stream file to MPV - it doesn't idle after playing FIFO
This commit is contained in:
@@ -119,7 +119,6 @@ func (p *PlaybackManager) addOnTrackChangeHook() {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
log.Println("updating waveform img, job step", job.step)
|
|
||||||
img := job.Get()
|
img := job.Get()
|
||||||
for _, cb := range p.onWaveformImgUpdate {
|
for _, cb := range p.onWaveformImgUpdate {
|
||||||
cb(img)
|
cb(img)
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ func (fs *FileStreamerServer) Serve() error {
|
|||||||
_ = fs.server.Serve(fs.listener)
|
_ = fs.server.Serve(fs.listener)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Println("Serving and WAITING for done")
|
|
||||||
<-fs.done // wait for the handler to finish
|
<-fs.done // wait for the handler to finish
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
@@ -61,13 +60,9 @@ func (fs *FileStreamerServer) Serve() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handler that streams the file using chunked transfer encoding.
|
// Handler that streams the file using chunked transfer encoding.
|
||||||
func (fs *FileStreamerServer) streamHandler(w http.ResponseWriter, r *http.Request) {
|
func (fs *FileStreamerServer) streamHandler(w http.ResponseWriter, _ *http.Request) {
|
||||||
log.Println("FILE STREAMER REQUEST")
|
|
||||||
defer close(fs.done) // signal Serve() to shut down after this request
|
defer close(fs.done) // signal Serve() to shut down after this request
|
||||||
|
|
||||||
totalWrote := 0
|
|
||||||
defer log.Println("File streamer wrote", totalWrote, "bytes")
|
|
||||||
|
|
||||||
file, err := os.Open(fs.Path)
|
file, err := os.Open(fs.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("File streamer failed to open source file")
|
log.Println("File streamer failed to open source file")
|
||||||
@@ -92,7 +87,7 @@ func (fs *FileStreamerServer) streamHandler(w http.ResponseWriter, r *http.Reque
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
written, err := w.Write(buf[:n])
|
_, err := w.Write(buf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("client write error: %v", err)
|
log.Printf("client write error: %v", err)
|
||||||
break
|
break
|
||||||
@@ -100,7 +95,6 @@ func (fs *FileStreamerServer) streamHandler(w http.ResponseWriter, r *http.Reque
|
|||||||
if canFlush {
|
if canFlush {
|
||||||
flusher.Flush()
|
flusher.Flush()
|
||||||
}
|
}
|
||||||
totalWrote += written
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n == 0 && complete {
|
if n == 0 && complete {
|
||||||
|
|||||||
+12
-72
@@ -15,10 +15,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
|
"github.com/dweymouth/supersonic/backend/util"
|
||||||
"github.com/go-audio/audio"
|
"github.com/go-audio/audio"
|
||||||
"github.com/go-audio/wav"
|
"github.com/go-audio/wav"
|
||||||
"github.com/supersonic-app/go-mpv"
|
"github.com/supersonic-app/go-mpv"
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type WaveformImageGenerator struct {
|
type WaveformImageGenerator struct {
|
||||||
@@ -135,9 +135,17 @@ func (w *WaveformImageGenerator) StartWaveformGeneration(item *mediaprovider.Tra
|
|||||||
// stream it to MPV via fifo so it doesn't possibly
|
// stream it to MPV via fifo so it doesn't possibly
|
||||||
// terminate the conversion to WAV early encountering EOF
|
// terminate the conversion to WAV early encountering EOF
|
||||||
if !fileDone() {
|
if !fileDone() {
|
||||||
fifoPath := filepath.Join(filepath.Dir(path), filepath.Base(path)+"_fifo")
|
srv, err := util.NewFileStreamerServer(path, fileDone)
|
||||||
copyFileToFifo(ctx, job, path, fifoPath, fileDone)
|
if err != nil {
|
||||||
path = fifoPath // MPV will read from the FIFO
|
job.setError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
path = srv.Addr()
|
||||||
|
|
||||||
|
log.Println("streaming file to MPV at ", path)
|
||||||
|
go srv.Serve()
|
||||||
|
time.Sleep(10 * time.Millisecond) // make sure server has time to come up
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start converting the file to WAV for analysis
|
// Start converting the file to WAV for analysis
|
||||||
@@ -237,71 +245,6 @@ func generateWaveformImage(ctx context.Context, data *waveformData, job *Wavefor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFileToFifo(ctx context.Context, job *WaveformImageJob, filePath, fifoPath string, fileDone func() bool) {
|
|
||||||
if err := unix.Mkfifo(fifoPath, 0600); err != nil {
|
|
||||||
job.setError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
fifo, err := os.OpenFile(fifoPath, os.O_WRONLY, os.ModeNamedPipe)
|
|
||||||
if err != nil {
|
|
||||||
job.setError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
file, err := os.Open(filePath)
|
|
||||||
if err != nil {
|
|
||||||
job.setError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
defer fifo.Close()
|
|
||||||
|
|
||||||
buf := make([]byte, 4096)
|
|
||||||
offset := int64(0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
if e := ctx.Err(); e != nil {
|
|
||||||
job.setError(e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
done := fileDone()
|
|
||||||
info, err := os.Stat(filePath)
|
|
||||||
if err != nil {
|
|
||||||
job.setError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
currentSize := info.Size()
|
|
||||||
|
|
||||||
// If we've read everything available so far
|
|
||||||
if offset >= currentSize {
|
|
||||||
if done {
|
|
||||||
return // done
|
|
||||||
}
|
|
||||||
// wait a bit for more data to be written to file
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate how much is safe to read
|
|
||||||
toRead := currentSize - offset - 1
|
|
||||||
if toRead > int64(cap(buf)) {
|
|
||||||
toRead = int64(cap(buf))
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := file.ReadAt(buf[:toRead], offset)
|
|
||||||
if n > 0 {
|
|
||||||
if _, werr := fifo.Write(buf[:n]); werr != nil {
|
|
||||||
job.setError(werr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
offset += int64(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// assumes mono, 16 bit
|
// assumes mono, 16 bit
|
||||||
func analyzeWavFile(ctx context.Context, transcodeFile string, data *waveformData, millisecs int64, fileDone func() bool) error {
|
func analyzeWavFile(ctx context.Context, transcodeFile string, data *waveformData, millisecs int64, fileDone func() bool) error {
|
||||||
f, err := os.Open(transcodeFile)
|
f, err := os.Open(transcodeFile)
|
||||||
@@ -379,8 +322,6 @@ func analyzeWavFile(ctx context.Context, transcodeFile string, data *waveformDat
|
|||||||
if err == io.EOF && !fileDone() {
|
if err == io.EOF && !fileDone() {
|
||||||
return errors.New("WAV read got premature EOF")
|
return errors.New("WAV read got premature EOF")
|
||||||
}
|
}
|
||||||
} else if fileIsDone {
|
|
||||||
log.Println("read samples on done file")
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -401,7 +342,6 @@ func analyzeWavFile(ctx context.Context, transcodeFile string, data *waveformDat
|
|||||||
data.progress = curChunk
|
data.progress = curChunk
|
||||||
chunkSamples = chunkSamples[:0]
|
chunkSamples = chunkSamples[:0]
|
||||||
if curChunk >= 1024 {
|
if curChunk >= 1024 {
|
||||||
doneReading = true
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user