This commit is contained in:
Linrador 2026-06-11 08:21:00 +02:00
parent d7e22952a6
commit e211ad34ab
2 changed files with 23 additions and 18 deletions

View File

@ -965,7 +965,7 @@ func recordAnalyzeVideo(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 30*time.Minute) ctx, cancel := context.WithTimeout(r.Context(), 30*time.Minute)
defer cancel() defer cancel()
hits, err := analyzeVideoFromFrames(ctx, outPath) hits, analyzeStartedAtMs, analyzeTotalFrames, err := analyzeVideoFromFrames(ctx, outPath)
if err != nil { if err != nil {
logAnalyzeError("analyze-frames", file, outPath, err) logAnalyzeError("analyze-frames", file, outPath, err)
@ -979,6 +979,10 @@ func recordAnalyzeVideo(w http.ResponseWriter, r *http.Request) {
return return
} }
// Wichtig: publishAnalysisFinished erst NACH writeVideoAIForFile feuern,
// damit refreshDoneMetaForFile im Frontend das Rating bereits in der Datei vorfindet.
defer publishAnalysisFinished(analyzeStartedAtMs, analyzeTotalFrames, file, "Analyse abgeschlossen")
appLogf("🧪 [analyze] hits file=%q count=%d", file, len(hits)) appLogf("🧪 [analyze] hits file=%q count=%d", file, len(hits))
durationSec, derr := durationSecondsForAnalyze(ctx, outPath) durationSec, derr := durationSecondsForAnalyze(ctx, outPath)
@ -1617,7 +1621,7 @@ func appendHighlightHitsFromPrediction(
return append(hits, next...) return append(hits, next...)
} }
func analyzeVideoFromFrames(ctx context.Context, outPath string) ([]analyzeHit, error) { func analyzeVideoFromFrames(ctx context.Context, outPath string) ([]analyzeHit, int64, int, error) {
return analyzeVideoFromFramesForGoal(ctx, outPath) return analyzeVideoFromFramesForGoal(ctx, outPath)
} }
@ -1743,9 +1747,9 @@ func analyzeGlobalPercentMessageFromCurrent(current int, total int) string {
func analyzeVideoFromFramesForGoal( func analyzeVideoFromFramesForGoal(
ctx context.Context, ctx context.Context,
outPath string, outPath string,
) (highlightHits []analyzeHit, err error) { ) (highlightHits []analyzeHit, startedAtMs int64, totalFrames int, err error) {
file := filepath.Base(strings.TrimSpace(outPath)) file := filepath.Base(strings.TrimSpace(outPath))
startedAtMs := publishAnalysisStarted(file, analyzeProgressTotal, "Analyse 0%") startedAtMs = publishAnalysisStarted(file, analyzeProgressTotal, "Analyse 0%")
publishAnalyzeExtractProgress( publishAnalyzeExtractProgress(
startedAtMs, startedAtMs,
@ -1756,19 +1760,19 @@ func analyzeVideoFromFramesForGoal(
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err) publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err)
return nil, err return nil, startedAtMs, 0, err
} }
durationSec, _ := durationSecondsForAnalyze(ctx, outPath) durationSec, _ := durationSecondsForAnalyze(ctx, outPath)
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err) publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err)
return nil, err return nil, startedAtMs, 0, err
} }
if durationSec <= 0 { if durationSec <= 0 {
err := appErrorf("videolänge konnte nicht bestimmt werden") err := appErrorf("videolänge konnte nicht bestimmt werden")
publishAnalysisError(startedAtMs, file, "Analyse fehlgeschlagen", err) publishAnalysisError(startedAtMs, file, "Analyse fehlgeschlagen", err)
return nil, err return nil, startedAtMs, 0, err
} }
publishPercentRange := func(lastPercent *int, nextPercent int, current int, total int, extractPhase bool) { publishPercentRange := func(lastPercent *int, nextPercent int, current int, total int, extractPhase bool) {
@ -1827,14 +1831,14 @@ func analyzeVideoFromFramesForGoal(
*lastPercent = nextPercent *lastPercent = nextPercent
} }
failCancelled := func() ([]analyzeHit, error) { failCancelled := func() ([]analyzeHit, int64, int, error) {
err := ctx.Err() err := ctx.Err()
if err == nil { if err == nil {
err = context.Canceled err = context.Canceled
} }
publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err) publishAnalysisError(startedAtMs, file, "Analyse abgebrochen", err)
return nil, err return nil, startedAtMs, 0, err
} }
lastExtractPercent := 0 lastExtractPercent := 0
@ -1880,13 +1884,13 @@ func analyzeVideoFromFramesForGoal(
if err != nil { if err != nil {
publishAnalysisError(startedAtMs, file, "Frames konnten nicht extrahiert werden", err) publishAnalysisError(startedAtMs, file, "Frames konnten nicht extrahiert werden", err)
return nil, err return nil, startedAtMs, 0, err
} }
if len(samples) == 0 { if len(samples) == 0 {
err := appErrorf("keine frame-samples vorhanden") err := appErrorf("keine frame-samples vorhanden")
publishAnalysisError(startedAtMs, file, "Keine Frames vorhanden", err) publishAnalysisError(startedAtMs, file, "Keine Frames vorhanden", err)
return nil, err return nil, startedAtMs, 0, err
} }
total := len(samples) total := len(samples)
@ -2043,8 +2047,7 @@ func analyzeVideoFromFramesForGoal(
cleanHighlightHits := mergeAnalyzeHits(highlightHits) cleanHighlightHits := mergeAnalyzeHits(highlightHits)
publishAnalysisFinished(startedAtMs, total, file, "Analyse abgeschlossen") return cleanHighlightHits, startedAtMs, total, nil
return cleanHighlightHits, nil
} }
// Fallback: langsame Einzelbild-Analyse, nur wenn der AI-Server-Batch fehlschlägt. // Fallback: langsame Einzelbild-Analyse, nur wenn der AI-Server-Batch fehlschlägt.
@ -2093,9 +2096,7 @@ func analyzeVideoFromFramesForGoal(
cleanHighlightHits := mergeAnalyzeHits(highlightHits) cleanHighlightHits := mergeAnalyzeHits(highlightHits)
publishAnalysisFinished(startedAtMs, total, file, "Analyse abgeschlossen") return cleanHighlightHits, startedAtMs, total, nil
return cleanHighlightHits, nil
} }
func sameAnalyzeComboLabel(a, b string) bool { func sameAnalyzeComboLabel(a, b string) bool {

View File

@ -172,11 +172,13 @@ func ensureAnalyzeAllGoalsForVideoCtxForce(
return false, skipAnalysisBecauseBadSpriteError(reason) return false, skipAnalysisBecauseBadSpriteError(reason)
} }
hits, err := analyzeVideoFromFrames(actx, videoPath) hits, analyzeStartedAtMs, analyzeTotalFrames, err := analyzeVideoFromFrames(actx, videoPath)
if err != nil { if err != nil {
return false, err return false, err
} }
defer publishAnalysisFinished(analyzeStartedAtMs, analyzeTotalFrames, filepath.Base(videoPath), "Analyse abgeschlossen")
segments := buildAnalyzeSegmentsForGoal(hits, durationSec) segments := buildAnalyzeSegmentsForGoal(hits, durationSec)
segments = prepareAIRatingSegments(segments) segments = prepareAIRatingSegments(segments)
@ -1585,11 +1587,13 @@ func prepareVideoForSplit(ctx context.Context, videoPath, sourceURL, goal string
return out, nil return out, nil
} }
hits, aerr := analyzeVideoFromFrames(ctx, videoPath) hits, analyzeStartedAtMs2, analyzeTotalFrames2, aerr := analyzeVideoFromFrames(ctx, videoPath)
if aerr != nil { if aerr != nil {
return out, nil return out, nil
} }
defer publishAnalysisFinished(analyzeStartedAtMs2, analyzeTotalFrames2, filepath.Base(videoPath), "Analyse abgeschlossen")
segments := buildAnalyzeSegmentsForGoal(hits, durationSec) segments := buildAnalyzeSegmentsForGoal(hits, durationSec)
segments = prepareAIRatingSegments(segments) segments = prepareAIRatingSegments(segments)