(a, b, fps, scope)
| 551 | } |
| 552 | |
| 553 | function toneFromStats(a, b, fps, scope) { |
| 554 | const brightnessDelta = (a.mean - b.mean) / 255; |
| 555 | const contrastRatio = Math.max(0.5, Math.min(1.8, a.std / Math.max(1, b.std))); |
| 556 | const meanPct = ((b.mean - a.mean) / 255) * 100; |
| 557 | const contrastPct = ((b.std - a.std) / Math.max(1, a.std)) * 100; |
| 558 | const severity = Math.max(Math.abs(meanPct), Math.abs(contrastPct) * 0.65); |
| 559 | const recommended = severity >= 1.0; |
| 560 | const frames = recommended ? Math.max(6, Math.min(18, Math.round(fps * 0.5))) : 0; |
| 561 | |
| 562 | return { |
| 563 | recommended, |
| 564 | frames, |
| 565 | brightnessDelta, |
| 566 | contrastRatio, |
| 567 | mean1: a.mean / 255, |
| 568 | mean2: b.mean / 255, |
| 569 | contrast1: a.std / 255, |
| 570 | contrast2: b.std / 255, |
| 571 | meanDeltaPct: meanPct, |
| 572 | contrastDeltaPct: contrastPct, |
| 573 | note: recommended |
| 574 | ? `${meanPct > 0 ? "brighter" : "darker"} by ${Math.abs(meanPct).toFixed(1)}% with ${Math.abs(contrastPct).toFixed(1)}% contrast shift.` |
| 575 | : "brightness and contrast are close." |
| 576 | }; |
| 577 | } |
| 578 | |
| 579 | function analyzeFrames(video1Frames, video2Frames, fps) { |
| 580 | const window = Math.min(WINDOW_FRAMES, video1Frames.length, video2Frames.length); |
no outgoing calls
no test coverage detected