mirror of https://github.com/stashapp/stash.git
Strip file extension from scene title when scanning (#1022)
This commit is contained in:
parent
4fc0d47087
commit
1882b44951
|
@ -34,6 +34,8 @@ input ScanMetadataInput {
|
|||
paths: [String!]
|
||||
"""Set name, date, details from metadata (if present)"""
|
||||
useFileMetadata: Boolean!
|
||||
"""Strip file extension from title"""
|
||||
stripFileExtension: Boolean!
|
||||
"""Generate previews during scan"""
|
||||
scanGeneratePreviews: Boolean!
|
||||
"""Generate image previews during scan"""
|
||||
|
|
|
@ -53,7 +53,7 @@ func getSceneFileContainer(scene *models.Scene) ffmpeg.Container {
|
|||
container = ffmpeg.Container(scene.Format.String)
|
||||
} else { // container isn't in the DB
|
||||
// shouldn't happen, fallback to ffprobe
|
||||
tmpVideoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path)
|
||||
tmpVideoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("[transcode] error reading video file: %s", err.Error())
|
||||
return ffmpeg.Container("")
|
||||
|
@ -100,7 +100,7 @@ func (rs sceneRoutes) StreamMp4(w http.ResponseWriter, r *http.Request) {
|
|||
func (rs sceneRoutes) StreamHLS(w http.ResponseWriter, r *http.Request) {
|
||||
scene := r.Context().Value(sceneKey).(*models.Scene)
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("[stream] error reading video file: %s", err.Error())
|
||||
return
|
||||
|
@ -136,7 +136,7 @@ func (rs sceneRoutes) streamTranscode(w http.ResponseWriter, r *http.Request, vi
|
|||
|
||||
// needs to be transcoded
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(manager.GetInstance().FFProbePath, scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("[stream] error reading video file: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -222,7 +222,7 @@ type VideoFile struct {
|
|||
}
|
||||
|
||||
// Execute exec command and bind result to struct.
|
||||
func NewVideoFile(ffprobePath string, videoPath string) (*VideoFile, error) {
|
||||
func NewVideoFile(ffprobePath string, videoPath string, stripExt bool) (*VideoFile, error) {
|
||||
args := []string{"-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", "-show_error", videoPath}
|
||||
//// Extremely slow on windows for some reason
|
||||
//if runtime.GOOS != "windows" {
|
||||
|
@ -239,10 +239,10 @@ func NewVideoFile(ffprobePath string, videoPath string) (*VideoFile, error) {
|
|||
return nil, fmt.Errorf("Error unmarshalling video data for <%s>: %s", videoPath, err.Error())
|
||||
}
|
||||
|
||||
return parse(videoPath, probeJSON)
|
||||
return parse(videoPath, probeJSON, stripExt)
|
||||
}
|
||||
|
||||
func parse(filePath string, probeJSON *FFProbeJSON) (*VideoFile, error) {
|
||||
func parse(filePath string, probeJSON *FFProbeJSON, stripExt bool) (*VideoFile, error) {
|
||||
if probeJSON == nil {
|
||||
return nil, fmt.Errorf("failed to get ffprobe json for <%s>", filePath)
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ func parse(filePath string, probeJSON *FFProbeJSON) (*VideoFile, error) {
|
|||
|
||||
if result.Title == "" {
|
||||
// default title to filename
|
||||
result.SetTitleFromPath()
|
||||
result.SetTitleFromPath(stripExt)
|
||||
}
|
||||
|
||||
result.Comment = probeJSON.Format.Tags.Comment
|
||||
|
@ -339,6 +339,11 @@ func (v *VideoFile) getStreamIndex(fileType string, probeJSON FFProbeJSON) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
func (v *VideoFile) SetTitleFromPath() {
|
||||
func (v *VideoFile) SetTitleFromPath(stripExtension bool) {
|
||||
v.Title = filepath.Base(v.Path)
|
||||
if stripExtension {
|
||||
ext := filepath.Ext(v.Title)
|
||||
v.Title = strings.TrimSuffix(v.Title, ext)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ func (s *singleton) Scan(input models.ScanMetadataInput) {
|
|||
instance.Paths.Generated.EnsureTmpDir()
|
||||
|
||||
wg.Add()
|
||||
task := ScanTask{FilePath: path, UseFileMetadata: input.UseFileMetadata, fileNamingAlgorithm: fileNamingAlgo, calculateMD5: calculateMD5, GeneratePreview: input.ScanGeneratePreviews, GenerateImagePreview: input.ScanGenerateImagePreviews, GenerateSprite: input.ScanGenerateSprites}
|
||||
task := ScanTask{FilePath: path, UseFileMetadata: input.UseFileMetadata, StripFileExtension: input.StripFileExtension, fileNamingAlgorithm: fileNamingAlgo, calculateMD5: calculateMD5, GeneratePreview: input.ScanGeneratePreviews, GenerateImagePreview: input.ScanGenerateImagePreviews, GenerateSprite: input.ScanGenerateSprites}
|
||||
go task.Start(&wg)
|
||||
|
||||
return nil
|
||||
|
|
|
@ -174,7 +174,7 @@ func GetSceneFileContainer(scene *models.Scene) (ffmpeg.Container, error) {
|
|||
container = ffmpeg.Container(scene.Format.String)
|
||||
} else { // container isn't in the DB
|
||||
// shouldn't happen, fallback to ffprobe
|
||||
tmpVideoFile, err := ffmpeg.NewVideoFile(GetInstance().FFProbePath, scene.Path)
|
||||
tmpVideoFile, err := ffmpeg.NewVideoFile(GetInstance().FFProbePath, scene.Path, false)
|
||||
if err != nil {
|
||||
return ffmpeg.Container(""), fmt.Errorf("error reading video file: %s", err.Error())
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ func (t *GenerateMarkersTask) Start(wg *sizedwaitgroup.SizedWaitGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("error reading video file: %s", err.Error())
|
||||
return
|
||||
|
@ -51,7 +51,7 @@ func (t *GenerateMarkersTask) generateSceneMarkers() {
|
|||
return
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("error reading video file: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -30,7 +30,7 @@ func (t *GeneratePreviewTask) Start(wg *sizedwaitgroup.SizedWaitGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("error reading video file: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -23,7 +23,7 @@ func (t *GenerateScreenshotTask) Start(wg *sync.WaitGroup) {
|
|||
defer wg.Done()
|
||||
|
||||
scenePath := t.Scene.Path
|
||||
probeResult, err := ffmpeg.NewVideoFile(instance.FFProbePath, scenePath)
|
||||
probeResult, err := ffmpeg.NewVideoFile(instance.FFProbePath, scenePath, false)
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
|
|
|
@ -22,7 +22,7 @@ func (t *GenerateSpriteTask) Start(wg *sizedwaitgroup.SizedWaitGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("error reading video file: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
type ScanTask struct {
|
||||
FilePath string
|
||||
UseFileMetadata bool
|
||||
StripFileExtension bool
|
||||
calculateMD5 bool
|
||||
fileNamingAlgorithm models.HashAlgorithm
|
||||
GenerateSprite bool
|
||||
|
@ -374,7 +375,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
|||
|
||||
// check for container
|
||||
if !scene.Format.Valid {
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath, t.StripFileExtension)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
return nil
|
||||
|
@ -455,7 +456,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
|||
return nil
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath, t.StripFileExtension)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
return nil
|
||||
|
@ -464,7 +465,7 @@ func (t *ScanTask) scanScene() *models.Scene {
|
|||
|
||||
// Override title to be filename if UseFileMetadata is false
|
||||
if !t.UseFileMetadata {
|
||||
videoFile.SetTitleFromPath()
|
||||
videoFile.SetTitleFromPath(t.StripFileExtension)
|
||||
}
|
||||
|
||||
var checksum string
|
||||
|
@ -588,7 +589,7 @@ func (t *ScanTask) rescanScene(scene *models.Scene, fileModTime time.Time) (*mod
|
|||
}
|
||||
|
||||
// regenerate the file details as well
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath, t.StripFileExtension)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -648,7 +649,7 @@ func (t *ScanTask) makeScreenshots(probeResult *ffmpeg.VideoFile, checksum strin
|
|||
|
||||
if probeResult == nil {
|
||||
var err error
|
||||
probeResult, err = ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath)
|
||||
probeResult, err = ffmpeg.NewVideoFile(instance.FFProbePath, t.FilePath, t.StripFileExtension)
|
||||
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
|
|
|
@ -30,7 +30,7 @@ func (t *GenerateTranscodeTask) Start(wg *sizedwaitgroup.SizedWaitGroup) {
|
|||
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)
|
||||
tmpVideoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("[transcode] error reading video file: %s", err.Error())
|
||||
return
|
||||
|
@ -49,7 +49,7 @@ func (t *GenerateTranscodeTask) Start(wg *sizedwaitgroup.SizedWaitGroup) {
|
|||
return
|
||||
}
|
||||
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path)
|
||||
videoFile, err := ffmpeg.NewVideoFile(instance.FFProbePath, t.Scene.Path, false)
|
||||
if err != nil {
|
||||
logger.Errorf("[transcode] error reading video file: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Allow configuration of visible navbar items.
|
||||
|
||||
### 🎨 Improvements
|
||||
* Add option to strip file extension from scene title when populating from scanning task.
|
||||
* Pagination support and general improvements for image lightbox.
|
||||
* Add mouse click support for CDP scrapers.
|
||||
* Add gallery tabs to performer and studio pages.
|
||||
|
|
|
@ -31,6 +31,7 @@ export const SettingsTasksPanel: React.FC = () => {
|
|||
const [isImportDialogOpen, setIsImportDialogOpen] = useState<boolean>(false);
|
||||
const [isScanDialogOpen, setIsScanDialogOpen] = useState<boolean>(false);
|
||||
const [useFileMetadata, setUseFileMetadata] = useState<boolean>(false);
|
||||
const [stripFileExtension, setStripFileExtension] = useState<boolean>(false);
|
||||
const [scanGeneratePreviews, setScanGeneratePreviews] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
|
@ -178,6 +179,7 @@ export const SettingsTasksPanel: React.FC = () => {
|
|||
await mutateMetadataScan({
|
||||
paths,
|
||||
useFileMetadata,
|
||||
stripFileExtension,
|
||||
scanGeneratePreviews,
|
||||
scanGenerateImagePreviews,
|
||||
scanGenerateSprites,
|
||||
|
@ -317,6 +319,12 @@ export const SettingsTasksPanel: React.FC = () => {
|
|||
label="Set name, date, details from metadata (if present)"
|
||||
onChange={() => setUseFileMetadata(!useFileMetadata)}
|
||||
/>
|
||||
<Form.Check
|
||||
id="strip-file-extension"
|
||||
checked={stripFileExtension}
|
||||
label="Don't include file extension as part of the title"
|
||||
onChange={() => setStripFileExtension(!stripFileExtension)}
|
||||
/>
|
||||
<Form.Check
|
||||
id="scan-generate-previews"
|
||||
checked={scanGeneratePreviews}
|
||||
|
|
Loading…
Reference in New Issue