初始提交:短剧库源码(含转码优化 ultrafast)
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type playbackRunContext struct {
|
||||
id string
|
||||
index int
|
||||
run uint64
|
||||
session *playbackSession
|
||||
task Task
|
||||
downloadID string
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
stop context.CancelFunc
|
||||
cache *playbackPrefetch
|
||||
offset float64
|
||||
}
|
||||
|
||||
func (app *UIApp) beginPlayback(parent context.Context, id string, index int, offset float64, quality int, version uint64, native bool) (*playbackRunContext, int, error) {
|
||||
app.playbackMu.Lock()
|
||||
session := app.playbacks[id]
|
||||
if !viewerOwnsPlayback(parent, session) {
|
||||
app.playbackMu.Unlock()
|
||||
return nil, http.StatusGone, errors.New("播放会话已过期,请重新打开本剧")
|
||||
}
|
||||
if index < 1 || index > len(session.tasks) {
|
||||
app.playbackMu.Unlock()
|
||||
return nil, http.StatusBadRequest, errors.New("分集不存在")
|
||||
}
|
||||
if version > 0 && version <= session.streamVersion {
|
||||
app.playbackMu.Unlock()
|
||||
return nil, http.StatusConflict, errors.New("播放请求已更新")
|
||||
}
|
||||
downloadID := ""
|
||||
if len(session.downloadIDs) > 0 {
|
||||
if !session.prepared[index] {
|
||||
app.playbackMu.Unlock()
|
||||
return nil, http.StatusConflict, errors.New("请先选择要播放的分集")
|
||||
}
|
||||
downloadID = session.downloadIDs[index-1]
|
||||
}
|
||||
previousCancel := session.cancel
|
||||
cache := session.prefetch
|
||||
session.prefetch, session.native, session.media = nil, nil, nil
|
||||
remux, _ := parent.Value(playbackRemuxKey{}).(bool)
|
||||
if cache != nil && (offset != 0 && !cache.planOnly || cache.episode != index || cache.fromRun != session.run || cache.quality != quality || (cache.native != nil) != native || !native && cache.remux != remux) {
|
||||
cache.cancel()
|
||||
cache = nil
|
||||
}
|
||||
ctx := context.WithValue(parent, playbackQualityKey{}, quality)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
stop := func() {
|
||||
cancel()
|
||||
if cache != nil {
|
||||
cache.cancel()
|
||||
}
|
||||
}
|
||||
session.cancel = stop
|
||||
session.run++
|
||||
session.currentIndex, session.quality = index, quality
|
||||
if version > 0 {
|
||||
session.streamVersion = version
|
||||
}
|
||||
if session.historyRuns == nil {
|
||||
session.historyRuns = make(map[uint64]playbackHistoryRun)
|
||||
}
|
||||
session.historyRuns[session.run] = playbackHistoryRun{episode: index}
|
||||
for oldRun := range session.historyRuns {
|
||||
if session.run > oldRun && session.run-oldRun > 8 {
|
||||
delete(session.historyRuns, oldRun)
|
||||
}
|
||||
}
|
||||
session.prefetchVersion = 0
|
||||
session.state, session.error, session.duration = "buffering", "", 0
|
||||
app.touchPlaybackLocked(session)
|
||||
run := &playbackRunContext{id: id, index: index, run: session.run, session: session, task: session.tasks[index-1], downloadID: downloadID, ctx: ctx, cancel: cancel, stop: stop, cache: cache, offset: offset}
|
||||
app.playbackMu.Unlock()
|
||||
if previousCancel != nil {
|
||||
previousCancel()
|
||||
}
|
||||
app.downloader.recordDiagnostic(diagnosticEvent{Level: "info", Event: "playback.started", Source: sourceFromDramaID(run.task.DramaID),
|
||||
DramaID: run.task.DramaID, DramaTitle: run.task.DramaTitle, Episode: index, Run: run.run, StartSeconds: offset, Message: "开始播放"})
|
||||
return run, http.StatusOK, nil
|
||||
}
|
||||
|
||||
func (app *UIApp) playbackRunReady(run *playbackRunContext, duration float64) {
|
||||
app.playbackMu.Lock()
|
||||
if current := app.playbacks[run.id]; current == run.session && current.run == run.run {
|
||||
current.state, current.duration = "streaming", duration
|
||||
current.historyRuns[run.run] = playbackHistoryRun{episode: run.index, duration: duration}
|
||||
}
|
||||
app.playbackMu.Unlock()
|
||||
}
|
||||
|
||||
func (app *UIApp) finishPlaybackRun(run *playbackRunContext, err error, stopped bool) {
|
||||
failed := false
|
||||
app.playbackMu.Lock()
|
||||
if current := app.playbacks[run.id]; current == run.session && current.run == run.run {
|
||||
if current.native == nil {
|
||||
current.cancel = nil
|
||||
}
|
||||
current.state = "ended"
|
||||
if err != nil {
|
||||
current.state, current.error = "failed", app.redactError(err)
|
||||
if stopped {
|
||||
current.state = "stopped"
|
||||
} else {
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
app.playbackMu.Unlock()
|
||||
if failed {
|
||||
app.downloader.recordTaskFailure("playback.failed", run.task, run.offset, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user