stash/pkg/manager/task_transcode.go

116 lines
3.1 KiB
Go

package manager
import (
"os"
"sync"
"github.com/stashapp/stash/pkg/ffmpeg"
"github.com/stashapp/stash/pkg/logger"
"github.com/stashapp/stash/pkg/manager/config"
"github.com/stashapp/stash/pkg/models"
)
type GenerateTranscodeTask struct {
Scene models.Scene
Overwrite bool
}
func (t *GenerateTranscodeTask) Start(wg *sync.WaitGroup) {
defer wg.Done()
hasTranscode, _ := HasTranscode(&t.Scene)
if !t.Overwrite && hasTranscode {
return
}
var container ffmpeg.Container
if t.Scene.Format.Valid {
container = ffmpeg.Container(t.Scene.Format.String)
} else { // container isn't in the DB
// shouldn't happen unless user hasn't scanned after updating to PR#384+ version
tmpVideoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
if err != nil {
logger.Errorf("[transcode] error reading video file: %s", err.Error())
return
}
container = ffmpeg.MatchContainer(tmpVideoFile.Container, t.Scene.Path)
}
videoCodec := t.Scene.VideoCodec.String
audioCodec := ffmpeg.MissingUnsupported
if t.Scene.AudioCodec.Valid {
audioCodec = ffmpeg.AudioCodec(t.Scene.AudioCodec.String)
}
if ffmpeg.IsStreamable(videoCodec, audioCodec, container) {
return
}
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
if err != nil {
logger.Errorf("[transcode] error reading video file: %s", err.Error())
return
}
outputPath := instance.Paths.Generated.GetTmpPath(t.Scene.Checksum + ".mp4")
transcodeSize := config.GetMaxTranscodeSize()
options := ffmpeg.TranscodeOptions{
OutputPath: outputPath,
MaxTranscodeSize: transcodeSize,
}
encoder := ffmpeg.NewEncoder(instance.FFMPEGPath)
if videoCodec == ffmpeg.H264 { // for non supported h264 files stream copy the video part
if audioCodec == ffmpeg.MissingUnsupported {
encoder.CopyVideo(*videoFile, options)
} else {
encoder.TranscodeAudio(*videoFile, options)
}
} else {
if audioCodec == ffmpeg.MissingUnsupported {
//ffmpeg fails if it trys to transcode an unsupported audio codec
encoder.TranscodeVideo(*videoFile, options)
} else {
encoder.Transcode(*videoFile, options)
}
}
if err := os.Rename(outputPath, instance.Paths.Scene.GetTranscodePath(t.Scene.Checksum)); err != nil {
logger.Errorf("[transcode] error generating transcode: %s", err.Error())
return
}
logger.Debugf("[transcode] <%s> created transcode: %s", t.Scene.Checksum, outputPath)
return
}
// return true if transcode is needed
// used only when counting files to generate, doesn't affect the actual transcode generation
// if container is missing from DB it is treated as non supported in order not to delay the user
func (t *GenerateTranscodeTask) isTranscodeNeeded() bool {
videoCodec := t.Scene.VideoCodec.String
container := ""
audioCodec := ffmpeg.MissingUnsupported
if t.Scene.AudioCodec.Valid {
audioCodec = ffmpeg.AudioCodec(t.Scene.AudioCodec.String)
}
if t.Scene.Format.Valid {
container = t.Scene.Format.String
}
if ffmpeg.IsStreamable(videoCodec, audioCodec, ffmpeg.Container(container)) {
return false
}
hasTranscode, _ := HasTranscode(&t.Scene)
if !t.Overwrite && hasTranscode {
return false
}
return true
}