Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 54 additions & 12 deletions pkg/component/operator/video/v0/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,24 @@ func compareFrame(c *qt.C, actual, expected format.Image) {
expectedImg, _, err := image.Decode(bytes.NewReader(expectedBinary.ByteArray()))
c.Assert(err, qt.IsNil)

// Calculate MSE
// Calculate MSE with pixel sampling for faster comparison
bounds := actualImg.Bounds()
var mse float64
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
step := 3 // Sample every 3rd pixel for faster comparison
sampledPixels := 0
for y := bounds.Min.Y; y < bounds.Max.Y; y += step {
for x := bounds.Min.X; x < bounds.Max.X; x += step {
actualColor := actualImg.At(x, y)
expectedColor := expectedImg.At(x, y)

ar, ag, ab, aa := actualColor.RGBA()
er, eg, eb, ea := expectedColor.RGBA()

mse += float64((ar-er)*(ar-er) + (ag-eg)*(ag-eg) + (ab-eb)*(ab-eb) + (aa-ea)*(aa-ea))
sampledPixels++
}
}
mse /= float64(bounds.Dx() * bounds.Dy() * 4) // 4 channels: R, G, B, A
mse /= float64(sampledPixels * 4) // 4 channels: R, G, B, A

// Calculate PSNR
if mse == 0 {
Expand All @@ -75,12 +78,24 @@ func compareAudio(c *qt.C, actual, expected format.Audio) {
actualBytes := actualBinary.ByteArray()
expectedBytes := expectedBinary.ByteArray()

// Handle different audio lengths by using the minimum length
minLen := len(actualBytes)
if len(expectedBytes) < minLen {
minLen = len(expectedBytes)
}

// For very different lengths, we should consider this a significant difference
if math.Abs(float64(len(actualBytes)-len(expectedBytes)))/float64(minLen) > 0.1 {
c.Assert(false, qt.IsTrue, qt.Commentf("Audio lengths differ significantly: actual=%d, expected=%d", len(actualBytes), len(expectedBytes)))
return
}

var mse float64
for i := 0; i < len(actualBytes); i++ {
for i := 0; i < minLen; i++ {
diff := float64(actualBytes[i]) - float64(expectedBytes[i])
mse += diff * diff
}
mse /= float64(len(actualBytes))
mse /= float64(minLen)

if mse == 0 {
c.Assert(true, qt.IsTrue, qt.Commentf("Audio signals are identical"))
Expand Down Expand Up @@ -112,16 +127,40 @@ func compareVideo(c *qt.C, actual, expected format.Video) {
qt.Commentf("Frame count differs by more than 1%%: got %d, want %d",
len(actualFrames), len(expectedFrames)))

// Compare each frame using PSNR
for i := 0; i < len(actualFrames); i++ {
// Compare frames using smart sampling for efficiency
maxFrames := len(actualFrames)
if len(expectedFrames) < maxFrames {
maxFrames = len(expectedFrames)
}

// For videos with many frames, sample key frames
framesToCompare := []int{}
if maxFrames <= 5 {
// Compare all frames for short videos
for i := 0; i < maxFrames; i++ {
framesToCompare = append(framesToCompare, i)
}
} else {
// For longer videos, compare first, last, middle, and a few samples
framesToCompare = append(framesToCompare, 0) // first frame
framesToCompare = append(framesToCompare, maxFrames/4) // quarter point
framesToCompare = append(framesToCompare, maxFrames/2) // middle
framesToCompare = append(framesToCompare, 3*maxFrames/4) // three-quarter point
framesToCompare = append(framesToCompare, maxFrames-1) // last frame
}

for _, i := range framesToCompare {
compareFrame(c, actualFrames[i], expectedFrames[i])
}
}

func extractFramesWithFFmpeg(video format.Video) ([]format.Image, error) {
// Use shorter UUID for temp directory
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("frames-%s", uuid.New().String()[:8]))
defer func() {
os.RemoveAll(tmpDir) // Ensure cleanup even on error
}()

tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("frames-%s", uuid.New().String()))
defer os.RemoveAll(tmpDir)
if err := os.MkdirAll(tmpDir, 0755); err != nil {
return nil, fmt.Errorf("creating temp dir: %w", err)
}
Expand All @@ -139,10 +178,12 @@ func extractFramesWithFFmpeg(video format.Video) ([]format.Image, error) {

err = ffmpeg.Input(inputFile).
Output(outputPattern, ffmpeg.KwArgs{
"vf": "fps=1",
"vf": "fps=1,scale=160:120", // Reduced resolution for faster processing
"pix_fmt": "rgb24",
"q:v": "8", // Faster encoding with acceptable quality
}).
OverWriteOutput().
Silent(true).
Run()
if err != nil {
return nil, fmt.Errorf("extracting frames: %w", err)
Expand All @@ -153,7 +194,8 @@ func extractFramesWithFFmpeg(video format.Video) ([]format.Image, error) {
return nil, fmt.Errorf("reading frames directory: %w", err)
}

var frames []format.Image
// Pre-allocate slice for better performance
frames := make([]format.Image, 0, len(files))
for _, file := range files {
if filepath.Ext(file.Name()) != ".png" {
continue
Expand Down
1 change: 1 addition & 0 deletions pkg/component/operator/video/v0/task_embed_audio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestEmbedAudio(t *testing.T) {

for _, tc := range testCases {
c.Run(tc.name, func(c *qt.C) {
c.Parallel()
component := Init(base.Component{})
c.Assert(component, qt.IsNotNil)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func TestExtractAudio(t *testing.T) {

for _, tc := range testCases {
c.Run(tc.name, func(c *qt.C) {
c.Parallel()
component := Init(base.Component{})
c.Assert(component, qt.IsNotNil)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func TestExtractFrames(t *testing.T) {

for _, tc := range testCases {
c.Run(tc.name, func(c *qt.C) {
c.Parallel()
component := Init(base.Component{})
c.Assert(component, qt.IsNotNil)

Expand Down
1 change: 1 addition & 0 deletions pkg/component/operator/video/v0/task_segment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestSegment(t *testing.T) {

for _, tc := range testCases {
c.Run(tc.name, func(c *qt.C) {
c.Parallel()
component := Init(base.Component{})
c.Assert(component, qt.IsNotNil)

Expand Down
1 change: 1 addition & 0 deletions pkg/component/operator/video/v0/task_subsample_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func TestSubsample(t *testing.T) {

for _, tc := range testCases {
c.Run(tc.name, func(c *qt.C) {
c.Parallel()
component := Init(base.Component{})
c.Assert(component, qt.IsNotNil)

Expand Down
Loading