diff --git a/.github/workflows/visualmetrics.yml b/.github/workflows/visualmetrics.yml new file mode 100644 index 000000000..022eb00d1 --- /dev/null +++ b/.github/workflows/visualmetrics.yml @@ -0,0 +1,27 @@ +name: Visual Metrics Regression +on: + push: + branches: + - main + paths: + - 'visualmetrics/**' + pull_request: + branches: + - main + paths: + - 'visualmetrics/**' +jobs: + regression: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Install ffmpeg + run: sudo apt-get update && sudo apt-get install -y ffmpeg + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: '3.11' + - name: Install Python dependencies + run: pip install numpy opencv-python-headless Pillow pyssim + - name: Run visual metrics regression tests + run: python visualmetrics/test_visual_metrics_regression.py -v diff --git a/visualmetrics/test_videos/aftonbladet_android.mp4 b/visualmetrics/test_videos/aftonbladet_android.mp4 new file mode 100644 index 000000000..610f931a3 Binary files /dev/null and b/visualmetrics/test_videos/aftonbladet_android.mp4 differ diff --git a/visualmetrics/test_videos/aftonbladet_chrome.mp4 b/visualmetrics/test_videos/aftonbladet_chrome.mp4 new file mode 100644 index 000000000..99d4dffd2 Binary files /dev/null and b/visualmetrics/test_videos/aftonbladet_chrome.mp4 differ diff --git a/visualmetrics/test_videos/aftonbladet_chrome_cable.mp4 b/visualmetrics/test_videos/aftonbladet_chrome_cable.mp4 new file mode 100644 index 000000000..b3ccfa0c5 Binary files /dev/null and b/visualmetrics/test_videos/aftonbladet_chrome_cable.mp4 differ diff --git a/visualmetrics/test_videos/amazon_chrome.mp4 b/visualmetrics/test_videos/amazon_chrome.mp4 new file mode 100644 index 000000000..7e2a83e58 Binary files /dev/null and b/visualmetrics/test_videos/amazon_chrome.mp4 differ diff --git a/visualmetrics/test_videos/apple_firefox.mp4 b/visualmetrics/test_videos/apple_firefox.mp4 new file mode 100644 index 000000000..2ae6038af Binary files /dev/null and b/visualmetrics/test_videos/apple_firefox.mp4 differ diff --git a/visualmetrics/test_videos/bbc_firefox.mp4 b/visualmetrics/test_videos/bbc_firefox.mp4 new file mode 100644 index 000000000..b6fe6beb5 Binary files /dev/null and b/visualmetrics/test_videos/bbc_firefox.mp4 differ diff --git a/visualmetrics/test_videos/bing_firefox.mp4 b/visualmetrics/test_videos/bing_firefox.mp4 new file mode 100644 index 000000000..ef2258016 Binary files /dev/null and b/visualmetrics/test_videos/bing_firefox.mp4 differ diff --git a/visualmetrics/test_videos/cnet_firefox.mp4 b/visualmetrics/test_videos/cnet_firefox.mp4 new file mode 100644 index 000000000..9fdf4562e Binary files /dev/null and b/visualmetrics/test_videos/cnet_firefox.mp4 differ diff --git a/visualmetrics/test_videos/cnet_firefox_cable.mp4 b/visualmetrics/test_videos/cnet_firefox_cable.mp4 new file mode 100644 index 000000000..a225f0887 Binary files /dev/null and b/visualmetrics/test_videos/cnet_firefox_cable.mp4 differ diff --git a/visualmetrics/test_videos/dn_chrome.mp4 b/visualmetrics/test_videos/dn_chrome.mp4 new file mode 100644 index 000000000..869cc2a11 Binary files /dev/null and b/visualmetrics/test_videos/dn_chrome.mp4 differ diff --git a/visualmetrics/test_videos/dn_chrome_cable.mp4 b/visualmetrics/test_videos/dn_chrome_cable.mp4 new file mode 100644 index 000000000..bb80b56b4 Binary files /dev/null and b/visualmetrics/test_videos/dn_chrome_cable.mp4 differ diff --git a/visualmetrics/test_videos/duckduckgo_firefox.mp4 b/visualmetrics/test_videos/duckduckgo_firefox.mp4 new file mode 100644 index 000000000..69ec40a65 Binary files /dev/null and b/visualmetrics/test_videos/duckduckgo_firefox.mp4 differ diff --git a/visualmetrics/test_videos/expected_metrics.json b/visualmetrics/test_videos/expected_metrics.json new file mode 100644 index 000000000..f885b5b5a --- /dev/null +++ b/visualmetrics/test_videos/expected_metrics.json @@ -0,0 +1,211 @@ +{ + "aftonbladet_android": { + "FirstVisualChange": 1100, + "LastVisualChange": 4062, + "SpeedIndex": 2934, + "PerceptualSpeedIndex": 3383, + "PerceptualSpeedIndexProgress": "0=0, 1100=32, 1119=32, 1165=33, 1180=34, 1212=35, 1232=35, 1247=35, 1330=37, 1352=38, 1378=38, 1449=40, 1473=41, 1498=41, 1513=41, 1547=42, 1561=43, 1580=43, 1614=44, 1632=44, 1664=45, 1679=45, 1712=46, 1729=46, 1763=47, 1778=48, 1811=48, 1828=49, 1848=49, 1880=50, 1901=50, 1927=51, 1963=52, 1995=53, 2029=53, 2059=54, 2080=54, 2111=55, 2129=56, 2160=56, 2179=57, 2210=57, 2227=58, 2244=58, 2260=59, 2279=59, 2297=59, 2330=60, 2363=61, 2398=62, 2416=62, 2443=63, 2464=63, 2482=64, 2512=64, 2527=65, 2562=66, 2581=66, 2599=66, 2620=67, 2667=68, 2694=69, 2712=69, 2744=70, 2788=71, 2813=71, 2831=72, 2862=72, 2877=73, 2896=73, 2910=73, 2926=74, 2944=74, 2961=75, 2978=75, 2994=75, 3010=76, 3028=76, 3261=81, 3343=83, 3378=84, 3480=86, 4045=99, 4062=100", + "ContentfulSpeedIndex": 2211, + "ContentfulSpeedIndexProgress": "0=0, 1100=49, 1119=50, 1165=51, 1180=51, 1212=52, 1232=53, 1247=53, 1330=55, 1352=55, 1378=56, 1449=57, 1473=58, 1498=58, 1513=59, 1547=59, 1561=60, 1580=60, 1614=61, 1632=61, 1664=62, 1679=62, 1712=63, 1729=63, 1763=64, 1778=64, 1811=65, 1828=65, 1848=65, 1880=66, 1901=66, 1927=67, 1963=68, 1995=68, 2029=69, 2059=69, 2080=70, 2111=70, 2129=71, 2160=71, 2179=72, 2210=72, 2227=73, 2244=73, 2260=73, 2279=74, 2297=74, 2330=75, 2363=75, 2398=76, 2416=76, 2443=77, 2464=77, 2482=78, 2512=78, 2527=79, 2562=79, 2581=80, 2599=80, 2620=80, 2667=81, 2694=82, 2712=82, 2744=83, 2788=84, 2813=84, 2831=84, 2862=85, 2877=85, 2896=86, 2910=86, 2926=87, 2944=87, 2961=87, 2978=88, 2994=88, 3010=88, 3028=89, 3261=94, 3343=96, 3378=96, 3480=99, 4045=100, 4062=100", + "VisualProgress": "0=0, 1100=29, 1119=29, 1165=29, 1180=29, 1212=29, 1232=29, 1247=29, 1330=31, 1352=31, 1378=31, 1449=42, 1473=42, 1498=42, 1513=42, 1547=42, 1561=42, 1580=42, 1614=42, 1632=42, 1664=42, 1679=42, 1712=42, 1729=42, 1763=42, 1778=42, 1811=42, 1828=42, 1848=42, 1880=42, 1901=42, 1927=42, 1963=42, 1995=42, 2029=42, 2059=42, 2080=42, 2111=42, 2129=42, 2160=42, 2179=42, 2210=42, 2227=42, 2244=42, 2260=42, 2279=42, 2297=42, 2330=42, 2363=42, 2398=42, 2416=42, 2443=42, 2464=42, 2482=42, 2512=42, 2527=42, 2562=42, 2581=42, 2599=42, 2620=42, 2667=42, 2694=42, 2712=42, 2744=42, 2788=42, 2813=42, 2831=42, 2862=35, 2877=35, 2896=35, 2910=35, 2926=35, 2944=35, 2961=35, 2978=35, 2994=35, 3010=35, 3028=35, 3261=35, 3343=35, 3378=35, 3480=35, 4045=94, 4062=100", + "videoRecordingStart": 1653 + }, + "aftonbladet_chrome": { + "FirstVisualChange": 500, + "LastVisualChange": 1234, + "SpeedIndex": 992, + "PerceptualSpeedIndex": 907, + "PerceptualSpeedIndexProgress": "0=0, 500=55, 534=57, 567=59, 600=62, 634=64, 667=66, 700=69, 734=71, 767=73, 800=76, 834=78, 867=80, 900=83, 934=85, 967=87, 1000=90, 1034=92, 1067=95, 1100=97, 1134=98, 1167=98, 1200=99, 1234=100", + "ContentfulSpeedIndex": 775, + "ContentfulSpeedIndexProgress": "0=0, 500=64, 534=66, 567=68, 600=70, 634=72, 667=74, 700=76, 734=78, 767=80, 800=82, 834=84, 867=86, 900=88, 934=90, 967=92, 1000=94, 1034=96, 1067=98, 1100=99, 1134=99, 1167=99, 1200=100, 1234=100", + "VisualProgress": "0=0, 500=18, 534=18, 567=18, 600=18, 634=18, 667=18, 700=18, 734=19, 767=19, 800=19, 834=19, 867=19, 900=19, 934=19, 967=19, 1000=19, 1034=19, 1067=19, 1100=97, 1134=97, 1167=97, 1200=97, 1234=100", + "videoRecordingStart": 866 + }, + "aftonbladet_chrome_cable": { + "FirstVisualChange": 967, + "LastVisualChange": 4934, + "SpeedIndex": 3673, + "PerceptualSpeedIndex": 3490, + "PerceptualSpeedIndexProgress": "0=0, 967=27, 1000=28, 1034=29, 1067=29, 1100=30, 1134=31, 1167=31, 1200=32, 1234=33, 1267=33, 2100=50, 2134=51, 2167=52, 2200=52, 2234=53, 2267=54, 2300=54, 2334=55, 2367=56, 2400=56, 2434=57, 2467=58, 2500=58, 2534=59, 2567=60, 2600=61, 2634=61, 2667=62, 2700=63, 2734=63, 2767=64, 2800=65, 2834=65, 2867=66, 2900=67, 2934=68, 2967=68, 3000=69, 3034=70, 3067=70, 3100=71, 3134=72, 3167=72, 3200=73, 3234=74, 3267=75, 3300=75, 3334=76, 3367=77, 3400=77, 3434=78, 3467=79, 3500=79, 3534=80, 3567=81, 3600=81, 3634=82, 3667=83, 3700=83, 3734=84, 3767=85, 3800=85, 3834=86, 3867=87, 3900=87, 3934=88, 3967=89, 4000=89, 4034=90, 4067=91, 4100=91, 4134=92, 4167=93, 4200=93, 4234=94, 4400=97, 4434=98, 4467=98, 4500=98, 4534=98, 4567=98, 4600=99, 4634=99, 4667=99, 4700=99, 4734=99, 4767=99, 4800=99, 4834=99, 4867=99, 4900=99, 4934=100", + "ContentfulSpeedIndex": 2187, + "ContentfulSpeedIndexProgress": "0=0, 967=44, 1000=45, 1034=46, 1067=47, 1100=48, 1134=49, 1167=50, 1200=50, 1234=51, 1267=52, 2100=67, 2134=68, 2167=68, 2200=69, 2234=70, 2267=70, 2300=71, 2334=71, 2367=72, 2400=72, 2434=73, 2467=73, 2500=73, 2534=74, 2567=74, 2600=75, 2634=75, 2667=76, 2700=76, 2734=77, 2767=77, 2800=78, 2834=78, 2867=79, 2900=79, 2934=80, 2967=80, 3000=81, 3034=81, 3067=81, 3100=82, 3134=82, 3167=83, 3200=83, 3234=84, 3267=84, 3300=85, 3334=85, 3367=86, 3400=86, 3434=87, 3467=87, 3500=87, 3534=88, 3567=88, 3600=89, 3634=89, 3667=89, 3700=90, 3734=90, 3767=91, 3800=91, 3834=92, 3867=92, 3900=92, 3934=93, 3967=93, 4000=94, 4034=94, 4067=95, 4100=95, 4134=95, 4167=96, 4200=96, 4234=97, 4400=99, 4434=99, 4467=99, 4500=99, 4534=99, 4567=99, 4600=99, 4634=99, 4667=99, 4700=99, 4734=99, 4767=99, 4800=99, 4834=99, 4867=99, 4900=100, 4934=100", + "VisualProgress": "0=0, 967=12, 1000=12, 1034=12, 1067=12, 1100=12, 1134=12, 1167=12, 1200=12, 1234=12, 1267=12, 2100=24, 2134=24, 2167=24, 2200=24, 2234=24, 2267=25, 2300=28, 2334=28, 2367=28, 2400=28, 2434=28, 2467=28, 2500=28, 2534=28, 2567=28, 2600=28, 2634=28, 2667=28, 2700=28, 2734=28, 2767=28, 2800=28, 2834=27, 2867=27, 2900=27, 2934=27, 2967=27, 3000=27, 3034=27, 3067=27, 3100=27, 3134=27, 3167=27, 3200=27, 3234=27, 3267=27, 3300=27, 3334=27, 3367=27, 3400=27, 3434=28, 3467=28, 3500=28, 3534=28, 3567=28, 3600=28, 3634=28, 3667=28, 3700=28, 3734=28, 3767=28, 3800=28, 3834=28, 3867=28, 3900=28, 3934=28, 3967=28, 4000=28, 4034=28, 4067=28, 4100=28, 4134=28, 4167=28, 4200=28, 4234=28, 4400=28, 4434=97, 4467=97, 4500=97, 4534=97, 4567=97, 4600=97, 4634=97, 4667=97, 4700=97, 4734=97, 4767=97, 4800=97, 4834=97, 4867=97, 4900=97, 4934=100", + "videoRecordingStart": 866 + }, + "amazon_chrome": { + "FirstVisualChange": 1100, + "LastVisualChange": 10067, + "SpeedIndex": 3187, + "PerceptualSpeedIndex": 3234, + "PerceptualSpeedIndexProgress": "0=0, 1100=34, 1134=34, 1167=35, 1200=35, 1234=35, 1267=36, 1300=36, 1334=36, 1367=36, 1400=37, 1434=37, 1500=37, 1534=38, 1567=38, 1600=38, 1634=39, 1667=39, 1700=39, 1734=39, 1767=40, 1800=40, 1834=40, 1867=40, 1900=41, 1934=41, 1967=41, 2000=41, 2034=41, 2067=42, 2100=42, 2134=42, 2167=42, 2200=43, 2234=43, 2267=43, 2300=43, 2334=44, 2367=44, 2400=44, 2434=44, 2467=44, 2500=45, 2534=45, 2567=45, 2600=45, 2634=46, 2667=46, 2700=46, 2734=46, 2767=46, 2800=47, 2834=47, 2867=47, 2900=47, 2934=48, 2967=48, 3000=48, 3034=48, 3067=48, 3100=49, 3134=49, 3167=49, 3200=49, 3234=50, 3267=50, 3300=50, 3334=50, 3367=51, 3400=51, 3434=51, 3467=51, 3500=51, 3534=52, 3567=52, 3600=52, 3634=52, 3667=53, 3700=53, 3734=53, 3767=53, 3800=53, 3834=54, 3867=54, 3900=54, 3934=54, 3967=55, 4067=55, 4100=55, 4134=56, 4167=56, 4200=56, 4234=56, 4267=57, 4300=57, 4334=57, 4367=57, 4400=57, 4434=58, 4467=58, 4500=58, 4534=58, 4567=59, 4600=59, 4634=59, 4667=59, 4700=59, 4734=60, 4767=60, 4800=60, 4834=60, 4867=61, 4900=61, 4934=61, 4967=61, 5000=61, 5034=62, 5067=62, 5100=62, 5134=62, 5167=63, 5200=63, 5234=63, 5267=63, 5300=64, 5334=64, 5367=64, 5400=64, 5434=64, 5467=65, 5500=65, 5534=65, 5567=65, 5600=66, 5634=66, 5667=66, 5700=66, 5734=67, 5767=67, 5800=67, 5834=67, 5867=68, 5900=68, 5934=68, 5967=68, 6000=69, 6034=69, 6067=69, 6100=69, 6134=70, 6167=70, 6200=70, 6267=71, 6300=71, 6334=71, 6367=71, 6400=72, 6434=72, 6467=72, 6500=72, 6534=73, 6567=73, 6600=73, 6634=73, 6667=74, 6700=74, 6734=74, 6767=74, 6800=75, 6834=75, 6867=75, 6900=75, 6934=76, 6967=76, 7000=76, 7034=76, 7067=77, 7100=77, 7134=77, 7167=77, 7200=78, 7234=78, 7267=78, 7300=79, 7334=79, 7367=79, 7400=79, 7434=80, 7467=80, 7500=80, 7534=80, 7567=81, 7600=81, 7634=81, 7667=81, 7700=82, 7734=82, 7767=82, 7800=82, 7834=83, 7867=83, 7900=83, 7934=83, 7967=84, 8000=84, 8034=84, 8067=84, 8100=85, 8134=85, 8167=85, 8200=85, 8234=86, 8267=86, 8300=86, 8334=86, 8367=87, 8400=87, 8534=88, 8567=88, 8600=88, 8634=89, 8667=89, 8700=89, 8734=89, 8767=90, 8800=90, 8834=90, 8867=90, 8900=91, 8934=91, 8967=91, 9000=91, 9034=92, 9067=92, 9100=92, 9134=93, 9167=93, 9200=93, 9234=93, 9267=94, 9300=94, 9334=94, 9367=94, 9400=95, 9434=95, 9467=95, 9500=95, 9534=96, 9567=96, 9600=96, 9634=96, 9667=97, 9700=97, 9734=97, 9767=97, 9800=98, 9834=98, 9867=98, 9900=98, 9934=99, 9967=99, 10000=99, 10034=99, 10067=100", + "ContentfulSpeedIndex": 1602, + "ContentfulSpeedIndexProgress": "0=0, 1100=68, 1134=70, 1167=70, 1200=71, 1234=71, 1267=71, 1300=71, 1334=72, 1367=72, 1400=72, 1434=72, 1500=73, 1534=73, 1567=74, 1600=74, 1634=74, 1667=74, 1700=75, 1734=75, 1767=75, 1800=75, 1834=75, 1867=76, 1900=76, 1934=76, 1967=76, 2000=76, 2034=77, 2067=77, 2100=77, 2134=77, 2167=77, 2200=78, 2234=78, 2267=78, 2300=78, 2334=78, 2367=78, 2400=79, 2434=79, 2467=79, 2500=79, 2534=79, 2567=80, 2600=80, 2634=80, 2667=80, 2700=80, 2734=81, 2767=81, 2800=81, 2834=81, 2867=81, 2900=82, 2934=82, 2967=82, 3000=82, 3034=82, 3067=83, 3100=83, 3134=83, 3167=83, 3200=83, 3234=84, 3267=84, 3300=84, 3334=84, 3367=84, 3400=85, 3434=85, 3467=85, 3500=85, 3534=85, 3567=86, 3600=86, 3634=86, 3667=86, 3700=86, 3734=87, 3767=87, 3800=87, 3834=87, 3867=87, 3900=88, 3934=88, 3967=88, 4067=88, 4100=89, 4134=89, 4167=89, 4200=89, 4234=89, 4267=90, 4300=90, 4334=90, 4367=90, 4400=90, 4434=91, 4467=91, 4500=91, 4534=91, 4567=91, 4600=92, 4634=92, 4667=92, 4700=92, 4734=92, 4767=93, 4800=93, 4834=93, 4867=93, 4900=93, 4934=94, 4967=94, 5000=94, 5034=94, 5067=94, 5100=95, 5134=95, 5167=95, 5200=95, 5234=95, 5267=96, 5300=96, 5334=96, 5367=96, 5400=96, 5434=97, 5467=97, 5500=97, 5534=97, 5567=97, 5600=98, 5634=98, 5667=98, 5700=98, 5734=98, 5767=98, 5800=98, 5834=98, 5867=98, 5900=98, 5934=98, 5967=98, 6000=98, 6034=98, 6067=98, 6100=98, 6134=98, 6167=98, 6200=98, 6267=98, 6300=98, 6334=98, 6367=98, 6400=98, 6434=98, 6467=98, 6500=98, 6534=98, 6567=98, 6600=98, 6634=98, 6667=98, 6700=98, 6734=98, 6767=98, 6800=98, 6834=98, 6867=98, 6900=98, 6934=98, 6967=98, 7000=98, 7034=98, 7067=98, 7100=98, 7134=98, 7167=98, 7200=98, 7234=98, 7267=98, 7300=98, 7334=98, 7367=98, 7400=98, 7434=98, 7467=98, 7500=98, 7534=98, 7567=98, 7600=98, 7634=98, 7667=98, 7700=98, 7734=98, 7767=98, 7800=98, 7834=98, 7867=98, 7900=98, 7934=98, 7967=98, 8000=98, 8034=98, 8067=98, 8100=98, 8134=98, 8167=98, 8200=98, 8234=98, 8267=98, 8300=98, 8334=98, 8367=98, 8400=98, 8534=98, 8567=98, 8600=98, 8634=98, 8667=98, 8700=98, 8734=98, 8767=98, 8800=98, 8834=98, 8867=98, 8900=98, 8934=98, 8967=98, 9000=98, 9034=98, 9067=98, 9100=98, 9134=98, 9167=98, 9200=98, 9234=98, 9267=98, 9300=98, 9334=98, 9367=98, 9400=98, 9434=98, 9467=98, 9500=98, 9534=98, 9567=98, 9600=98, 9634=98, 9667=98, 9700=98, 9734=98, 9767=98, 9800=98, 9834=98, 9867=98, 9900=99, 9934=99, 9967=99, 10000=99, 10034=99, 10067=100", + "VisualProgress": "0=0, 1100=12, 1134=12, 1167=90, 1200=90, 1234=90, 1267=90, 1300=90, 1334=90, 1367=90, 1400=90, 1434=90, 1500=90, 1534=90, 1567=90, 1600=90, 1634=90, 1667=90, 1700=90, 1734=90, 1767=87, 1800=87, 1834=87, 1867=87, 1900=87, 1934=87, 1967=87, 2000=87, 2034=87, 2067=87, 2100=87, 2134=87, 2167=87, 2200=87, 2234=87, 2267=87, 2300=87, 2334=87, 2367=87, 2400=87, 2434=87, 2467=87, 2500=87, 2534=87, 2567=87, 2600=87, 2634=87, 2667=87, 2700=87, 2734=87, 2767=87, 2800=87, 2834=87, 2867=87, 2900=87, 2934=87, 2967=87, 3000=87, 3034=87, 3067=87, 3100=87, 3134=87, 3167=87, 3200=87, 3234=87, 3267=87, 3300=87, 3334=87, 3367=87, 3400=87, 3434=87, 3467=87, 3500=87, 3534=87, 3567=87, 3600=87, 3634=87, 3667=88, 3700=88, 3734=88, 3767=88, 3800=88, 3834=88, 3867=88, 3900=88, 3934=88, 3967=88, 4067=88, 4100=88, 4134=88, 4167=88, 4200=88, 4234=88, 4267=88, 4300=88, 4334=88, 4367=88, 4400=88, 4434=88, 4467=88, 4500=88, 4534=88, 4567=88, 4600=88, 4634=88, 4667=88, 4700=88, 4734=88, 4767=88, 4800=88, 4834=88, 4867=88, 4900=88, 4934=88, 4967=88, 5000=88, 5034=88, 5067=88, 5100=88, 5134=88, 5167=88, 5200=88, 5234=88, 5267=88, 5300=88, 5334=88, 5367=88, 5400=88, 5434=88, 5467=88, 5500=88, 5534=88, 5567=84, 5600=76, 5634=70, 5667=68, 5700=67, 5734=66, 5767=65, 5800=65, 5834=65, 5867=65, 5900=65, 5934=65, 5967=65, 6000=65, 6034=65, 6067=65, 6100=65, 6134=65, 6167=65, 6200=65, 6267=65, 6300=65, 6334=65, 6367=65, 6400=65, 6434=65, 6467=65, 6500=65, 6534=65, 6567=65, 6600=65, 6634=65, 6667=65, 6700=65, 6734=65, 6767=65, 6800=65, 6834=65, 6867=65, 6900=65, 6934=65, 6967=65, 7000=65, 7034=65, 7067=65, 7100=65, 7134=65, 7167=65, 7200=65, 7234=65, 7267=65, 7300=65, 7334=65, 7367=65, 7400=65, 7434=65, 7467=66, 7500=66, 7534=66, 7567=66, 7600=66, 7634=66, 7667=66, 7700=66, 7734=66, 7767=66, 7800=66, 7834=66, 7867=66, 7900=66, 7934=66, 7967=66, 8000=66, 8034=66, 8067=66, 8100=66, 8134=66, 8167=66, 8200=66, 8234=66, 8267=66, 8300=66, 8334=66, 8367=66, 8400=66, 8534=66, 8567=66, 8600=66, 8634=66, 8667=66, 8700=66, 8734=66, 8767=66, 8800=66, 8834=66, 8867=66, 8900=66, 8934=66, 8967=66, 9000=66, 9034=66, 9067=66, 9100=66, 9134=66, 9167=66, 9200=66, 9234=66, 9267=66, 9300=66, 9334=66, 9367=66, 9400=66, 9434=66, 9467=66, 9500=66, 9534=66, 9567=66, 9600=66, 9634=66, 9667=66, 9700=66, 9734=66, 9767=66, 9800=66, 9834=66, 9867=74, 9900=78, 9934=86, 9967=92, 10000=95, 10034=97, 10067=100", + "videoRecordingStart": 866 + }, + "apple_firefox": { + "FirstVisualChange": 166, + "LastVisualChange": 833, + "SpeedIndex": 247, + "PerceptualSpeedIndex": 189, + "PerceptualSpeedIndexProgress": "0=0, 166=87, 200=91, 233=95, 266=99, 300=99, 333=99, 366=99, 400=99, 433=99, 466=99, 500=99, 533=99, 566=99, 600=99, 633=99, 666=99, 700=99, 733=99, 766=99, 800=100, 833=100", + "ContentfulSpeedIndex": 293, + "ContentfulSpeedIndexProgress": "0=0, 166=56, 200=66, 233=75, 266=77, 300=78, 333=80, 366=81, 400=82, 433=84, 466=85, 500=87, 533=88, 566=90, 600=91, 633=92, 666=94, 700=95, 733=97, 766=98, 800=100, 833=100", + "VisualProgress": "0=0, 166=0, 200=0, 233=73, 266=99, 300=99, 333=99, 366=99, 400=99, 433=99, 466=99, 500=99, 533=99, 566=99, 600=99, 633=99, 666=99, 700=99, 733=99, 766=99, 800=99, 833=100", + "videoRecordingStart": 900 + }, + "bbc_firefox": { + "FirstVisualChange": 266, + "LastVisualChange": 700, + "SpeedIndex": 624, + "PerceptualSpeedIndex": 546, + "PerceptualSpeedIndexProgress": "0=0, 266=48, 300=52, 333=56, 366=60, 400=64, 433=67, 466=71, 500=75, 533=79, 566=83, 600=87, 633=91, 666=95, 700=100", + "ContentfulSpeedIndex": 478, + "ContentfulSpeedIndexProgress": "0=0, 266=55, 300=61, 333=66, 366=71, 400=75, 433=80, 466=85, 500=87, 533=90, 566=92, 600=95, 633=97, 666=100, 700=100", + "VisualProgress": "0=0, 266=3, 300=6, 333=11, 366=11, 400=11, 433=11, 466=11, 500=27, 533=27, 566=27, 600=27, 633=27, 666=27, 700=100", + "videoRecordingStart": 900 + }, + "bing_firefox": { + "FirstVisualChange": 333, + "LastVisualChange": 2566, + "SpeedIndex": 697, + "PerceptualSpeedIndex": 867, + "PerceptualSpeedIndexProgress": "0=0, 333=38, 366=40, 400=43, 433=46, 466=48, 500=51, 533=52, 566=54, 600=55, 633=56, 666=57, 700=58, 733=59, 766=61, 800=62, 833=63, 866=64, 900=65, 933=66, 966=67, 1000=68, 1033=69, 1066=70, 1100=71, 1133=72, 1166=73, 1200=74, 1233=75, 1266=76, 1300=77, 1333=78, 1366=79, 1400=80, 1433=81, 1466=82, 1500=83, 1533=83, 1566=84, 1600=85, 1633=86, 1666=87, 1700=88, 1733=89, 1766=89, 1800=90, 1833=91, 1866=91, 1900=92, 1933=93, 1966=93, 2000=94, 2033=95, 2066=96, 2100=97, 2133=97, 2166=98, 2200=98, 2233=99, 2266=99, 2300=99, 2333=99, 2366=99, 2400=99, 2433=99, 2466=100, 2500=100, 2533=100, 2566=100", + "ContentfulSpeedIndex": 590, + "ContentfulSpeedIndexProgress": "0=0, 333=56, 366=61, 400=66, 433=72, 466=77, 500=79, 533=81, 566=83, 600=84, 633=84, 666=84, 700=85, 733=85, 766=85, 800=85, 833=85, 866=85, 900=85, 933=85, 966=85, 1000=85, 1033=86, 1066=86, 1100=86, 1133=86, 1166=87, 1200=87, 1233=87, 1266=87, 1300=88, 1333=88, 1366=88, 1400=88, 1433=88, 1466=89, 1500=89, 1533=89, 1566=89, 1600=90, 1633=90, 1666=90, 1700=90, 1733=90, 1766=91, 1800=91, 1833=91, 1866=91, 1900=92, 1933=92, 1966=92, 2000=93, 2033=93, 2066=93, 2100=94, 2133=94, 2166=94, 2200=95, 2233=95, 2266=96, 2300=96, 2333=96, 2366=97, 2400=97, 2433=98, 2466=98, 2500=99, 2533=99, 2566=100", + "VisualProgress": "0=0, 333=18, 366=18, 400=18, 433=19, 466=19, 500=67, 533=68, 566=67, 600=72, 633=75, 666=75, 700=75, 733=75, 766=75, 800=75, 833=75, 866=76, 900=77, 933=79, 966=80, 1000=81, 1033=82, 1066=84, 1100=85, 1133=86, 1166=87, 1200=87, 1233=88, 1266=88, 1300=89, 1333=90, 1366=91, 1400=91, 1433=92, 1466=93, 1500=93, 1533=93, 1566=94, 1600=94, 1633=95, 1666=95, 1700=95, 1733=95, 1766=95, 1800=96, 1833=96, 1866=96, 1900=96, 1933=97, 1966=97, 2000=97, 2033=97, 2066=97, 2100=97, 2133=97, 2166=97, 2200=97, 2233=98, 2266=98, 2300=98, 2333=98, 2366=98, 2400=98, 2433=98, 2466=99, 2500=99, 2533=99, 2566=100", + "videoRecordingStart": 900 + }, + "cnet_firefox": { + "FirstVisualChange": 700, + "LastVisualChange": 2166, + "SpeedIndex": 1428, + "PerceptualSpeedIndex": 1007, + "PerceptualSpeedIndexProgress": "0=0, 700=69, 733=71, 766=73, 800=74, 833=76, 866=78, 900=80, 933=82, 966=84, 1000=85, 1033=87, 1066=89, 1100=91, 1133=93, 1166=94, 1200=95, 1233=96, 1266=97, 1300=97, 1333=98, 1366=98, 1400=99, 1433=99, 1466=99, 1500=99, 1533=99, 1566=99, 1600=99, 1633=99, 1666=99, 1766=99, 1800=99, 1833=99, 1866=99, 1900=99, 1933=99, 1966=99, 2000=99, 2033=99, 2066=99, 2100=100, 2133=100, 2166=100", + "ContentfulSpeedIndex": 1033, + "ContentfulSpeedIndexProgress": "0=0, 700=67, 733=70, 766=72, 800=74, 833=75, 866=77, 900=79, 933=81, 966=83, 1000=85, 1033=87, 1066=89, 1100=91, 1133=93, 1166=93, 1200=93, 1233=93, 1266=93, 1300=93, 1333=93, 1366=93, 1400=94, 1433=94, 1466=94, 1500=94, 1533=94, 1566=95, 1600=95, 1633=95, 1666=96, 1766=96, 1800=97, 1833=97, 1866=97, 1900=97, 1933=98, 1966=98, 2000=98, 2033=98, 2066=99, 2100=99, 2133=99, 2166=100", + "VisualProgress": "0=0, 700=9, 733=9, 766=11, 800=11, 833=11, 866=11, 900=11, 933=11, 966=11, 1000=11, 1033=11, 1066=11, 1100=11, 1133=11, 1166=18, 1200=18, 1233=18, 1266=18, 1300=18, 1333=18, 1366=19, 1400=19, 1433=21, 1466=23, 1500=26, 1533=96, 1566=96, 1600=97, 1633=97, 1666=97, 1766=97, 1800=97, 1833=97, 1866=97, 1900=97, 1933=97, 1966=98, 2000=98, 2033=98, 2066=98, 2100=98, 2133=98, 2166=100", + "videoRecordingStart": 900 + }, + "cnet_firefox_cable": { + "FirstVisualChange": 1733, + "LastVisualChange": 11366, + "SpeedIndex": 9807, + "PerceptualSpeedIndex": 7148, + "PerceptualSpeedIndexProgress": "0=0, 1733=24, 1766=24, 1800=24, 1833=25, 1866=25, 1900=25, 1933=25, 1966=26, 2000=26, 2033=26, 2066=27, 2100=27, 2133=27, 2166=27, 2200=28, 2233=28, 2266=28, 2300=29, 2333=29, 2366=29, 2400=30, 2433=30, 2466=30, 2500=30, 2533=31, 2566=31, 2600=31, 2633=32, 2666=32, 2700=32, 2733=32, 2766=33, 2800=33, 2833=33, 2866=34, 2900=34, 2933=34, 2966=35, 3000=35, 3033=35, 3066=35, 3100=36, 3133=36, 3166=36, 3200=37, 3233=37, 3266=37, 3300=37, 3333=38, 3366=38, 3400=38, 3433=39, 3466=39, 3500=39, 3533=39, 3566=40, 3600=40, 3633=40, 3666=41, 3700=41, 3733=41, 3766=42, 3800=42, 3833=42, 3866=42, 4700=50, 4733=50, 4766=50, 4800=51, 4833=51, 4866=51, 4900=51, 4933=52, 4966=52, 5000=52, 5033=53, 5066=53, 5100=53, 5133=54, 5166=54, 5200=54, 5233=54, 5266=55, 5300=55, 5333=55, 5366=56, 5400=56, 5433=56, 5466=56, 5500=57, 5533=57, 5566=57, 5600=58, 5633=58, 5666=58, 5700=58, 5733=59, 5766=59, 5800=59, 5833=60, 5866=60, 5900=60, 5933=60, 5966=61, 6000=61, 6033=61, 6066=62, 6100=62, 6133=62, 6166=63, 6200=63, 6233=63, 6266=63, 6300=64, 6333=64, 6366=64, 6400=65, 6433=65, 6466=65, 6500=65, 6533=66, 6566=66, 6600=66, 6633=67, 6666=67, 6700=67, 6733=67, 6766=68, 6800=68, 6833=68, 7433=74, 7466=74, 7500=74, 7533=74, 7566=75, 7600=75, 7633=75, 7666=76, 7700=76, 7733=76, 7766=77, 7800=77, 7833=77, 7866=77, 7900=78, 7933=78, 7966=78, 8000=79, 8033=79, 8066=79, 8100=79, 8133=80, 8166=80, 8200=80, 8233=81, 8266=81, 8300=81, 8333=81, 8366=82, 8400=82, 8433=82, 8466=83, 8500=83, 8533=83, 8566=83, 8600=84, 8633=84, 8666=84, 8700=85, 8733=85, 8766=85, 8800=85, 8833=86, 8866=86, 8900=86, 8933=86, 8966=87, 9000=87, 9033=87, 9066=88, 9100=88, 9133=88, 9166=88, 9200=89, 9233=89, 9266=89, 9300=90, 9333=90, 9366=90, 9400=90, 9433=91, 9466=91, 9500=91, 9533=92, 9566=92, 9600=92, 9700=93, 9733=93, 9766=94, 9800=94, 9833=94, 9866=94, 9900=95, 9933=95, 9966=95, 10000=96, 10033=96, 10066=96, 10100=96, 10133=97, 10166=97, 10200=97, 10233=98, 10266=98, 10300=98, 10333=98, 10366=99, 10400=99, 10433=99, 10466=99, 10500=99, 10533=99, 10566=99, 10600=99, 10633=99, 10666=99, 10700=99, 10733=99, 10766=99, 10800=99, 10833=99, 10866=99, 10900=99, 10933=99, 10966=99, 11000=99, 11033=99, 11066=99, 11100=99, 11133=99, 11166=99, 11200=99, 11233=100, 11266=100, 11300=100, 11333=100, 11366=100", + "ContentfulSpeedIndex": 7453, + "ContentfulSpeedIndexProgress": "0=0, 1733=23, 1766=23, 1800=23, 1833=24, 1866=24, 1900=24, 1933=25, 1966=25, 2000=26, 2033=26, 2066=26, 2100=27, 2133=27, 2166=27, 2200=28, 2233=28, 2266=28, 2300=29, 2333=29, 2366=29, 2400=30, 2433=30, 2466=30, 2500=31, 2533=31, 2566=31, 2600=32, 2633=32, 2666=33, 2700=33, 2733=33, 2766=34, 2800=34, 2833=34, 2866=35, 2900=35, 2933=35, 2966=36, 3000=36, 3033=36, 3066=37, 3100=37, 3133=37, 3166=38, 3200=38, 3233=38, 3266=39, 3300=39, 3333=39, 3366=40, 3400=40, 3433=41, 3466=41, 3500=41, 3533=42, 3566=42, 3600=42, 3633=43, 3666=43, 3700=43, 3733=44, 3766=44, 3800=44, 3833=45, 3866=45, 4700=53, 4733=53, 4766=53, 4800=54, 4833=54, 4866=54, 4900=54, 4933=55, 4966=55, 5000=55, 5033=56, 5066=56, 5100=56, 5133=56, 5166=57, 5200=57, 5233=57, 5266=58, 5300=58, 5333=58, 5366=58, 5400=59, 5433=59, 5466=59, 5500=60, 5533=60, 5566=60, 5600=60, 5633=61, 5666=61, 5700=61, 5733=62, 5766=62, 5800=62, 5833=62, 5866=63, 5900=63, 5933=63, 5966=64, 6000=64, 6033=64, 6066=65, 6100=65, 6133=65, 6166=65, 6200=66, 6233=66, 6266=66, 6300=67, 6333=67, 6366=67, 6400=67, 6433=68, 6466=68, 6500=68, 6533=69, 6566=69, 6600=69, 6633=69, 6666=70, 6700=70, 6733=70, 6766=71, 6800=71, 6833=71, 7433=76, 7466=77, 7500=77, 7533=77, 7566=77, 7600=78, 7633=78, 7666=78, 7700=79, 7733=79, 7766=79, 7800=79, 7833=80, 7866=80, 7900=80, 7933=81, 7966=81, 8000=81, 8033=81, 8066=82, 8100=82, 8133=82, 8166=82, 8200=83, 8233=83, 8266=83, 8300=84, 8333=84, 8366=84, 8400=84, 8433=85, 8466=85, 8500=85, 8533=85, 8566=86, 8600=86, 8633=86, 8666=87, 8700=87, 8733=87, 8766=87, 8800=88, 8833=88, 8866=88, 8900=88, 8933=89, 8966=89, 9000=89, 9033=90, 9066=90, 9100=90, 9133=90, 9166=91, 9200=91, 9233=91, 9266=92, 9300=92, 9333=92, 9366=92, 9400=92, 9433=93, 9466=93, 9500=93, 9533=93, 9566=94, 9600=94, 9700=94, 9733=95, 9766=95, 9800=95, 9833=95, 9866=96, 9900=96, 9933=96, 9966=96, 10000=96, 10033=97, 10066=97, 10100=97, 10133=97, 10166=98, 10200=98, 10233=98, 10266=98, 10300=98, 10333=99, 10366=99, 10400=99, 10433=99, 10466=99, 10500=99, 10533=99, 10566=99, 10600=99, 10633=99, 10666=99, 10700=99, 10733=99, 10766=99, 10800=99, 10833=99, 10866=99, 10900=99, 10933=99, 10966=99, 11000=99, 11033=99, 11066=99, 11100=99, 11133=99, 11166=99, 11200=99, 11233=99, 11266=99, 11300=99, 11333=99, 11366=100", + "VisualProgress": "0=0, 1733=7, 1766=7, 1800=7, 1833=7, 1866=7, 1900=7, 1933=7, 1966=7, 2000=7, 2033=7, 2066=7, 2100=7, 2133=7, 2166=7, 2200=7, 2233=7, 2266=7, 2300=7, 2333=7, 2366=7, 2400=7, 2433=7, 2466=7, 2500=7, 2533=7, 2566=7, 2600=7, 2633=7, 2666=7, 2700=7, 2733=7, 2766=7, 2800=7, 2833=7, 2866=7, 2900=7, 2933=7, 2966=7, 3000=7, 3033=7, 3066=7, 3100=7, 3133=7, 3166=7, 3200=7, 3233=7, 3266=7, 3300=7, 3333=7, 3366=7, 3400=7, 3433=7, 3466=7, 3500=7, 3533=7, 3566=7, 3600=7, 3633=7, 3666=7, 3700=7, 3733=7, 3766=7, 3800=7, 3833=7, 3866=7, 4700=9, 4733=10, 4766=10, 4800=10, 4833=10, 4866=10, 4900=10, 4933=10, 4966=10, 5000=10, 5033=10, 5066=10, 5100=10, 5133=10, 5166=10, 5200=10, 5233=10, 5266=10, 5300=10, 5333=10, 5366=10, 5400=10, 5433=10, 5466=10, 5500=10, 5533=10, 5566=10, 5600=10, 5633=10, 5666=10, 5700=10, 5733=10, 5766=10, 5800=10, 5833=10, 5866=10, 5900=10, 5933=10, 5966=10, 6000=10, 6033=10, 6066=10, 6100=10, 6133=10, 6166=10, 6200=10, 6233=10, 6266=10, 6300=10, 6333=10, 6366=10, 6400=10, 6433=10, 6466=10, 6500=10, 6533=10, 6566=10, 6600=10, 6633=10, 6666=10, 6700=10, 6733=10, 6766=10, 6800=10, 6833=10, 7433=10, 7466=10, 7500=10, 7533=10, 7566=10, 7600=10, 7633=10, 7666=10, 7700=10, 7733=10, 7766=10, 7800=10, 7833=10, 7866=10, 7900=10, 7933=10, 7966=10, 8000=10, 8033=10, 8066=10, 8100=10, 8133=10, 8166=10, 8200=10, 8233=10, 8266=10, 8300=10, 8333=10, 8366=10, 8400=10, 8433=10, 8466=10, 8500=10, 8533=10, 8566=10, 8600=10, 8633=10, 8666=10, 8700=10, 8733=10, 8766=10, 8800=10, 8833=10, 8866=10, 8900=10, 8933=10, 8966=10, 9000=10, 9033=10, 9066=10, 9100=10, 9133=10, 9166=10, 9200=10, 9233=10, 9266=10, 9300=17, 9333=17, 9366=17, 9400=17, 9433=17, 9466=17, 9500=17, 9533=17, 9566=17, 9600=17, 9700=17, 9733=17, 9766=17, 9800=17, 9833=17, 9866=17, 9900=17, 9933=17, 9966=17, 10000=17, 10033=17, 10066=17, 10100=17, 10133=17, 10166=17, 10200=17, 10233=17, 10266=17, 10300=17, 10333=17, 10366=20, 10400=20, 10433=21, 10466=21, 10500=22, 10533=23, 10566=24, 10600=24, 10633=26, 10666=27, 10700=64, 10733=95, 10766=96, 10800=96, 10833=97, 10866=97, 10900=97, 10933=97, 10966=97, 11000=97, 11033=97, 11066=97, 11100=97, 11133=97, 11166=97, 11200=97, 11233=97, 11266=97, 11300=97, 11333=97, 11366=100", + "videoRecordingStart": 900 + }, + "dn_chrome": { + "FirstVisualChange": 200, + "LastVisualChange": 534, + "SpeedIndex": 495, + "PerceptualSpeedIndex": 317, + "PerceptualSpeedIndexProgress": "0=0, 200=63, 234=66, 267=70, 300=73, 334=77, 367=81, 400=84, 434=88, 467=92, 500=96, 534=100", + "ContentfulSpeedIndex": 335, + "ContentfulSpeedIndexProgress": "0=0, 200=59, 234=66, 267=72, 300=76, 334=80, 367=84, 400=88, 434=92, 467=96, 500=100, 534=100", + "VisualProgress": "0=0, 200=10, 234=10, 267=11, 300=12, 334=12, 367=12, 400=12, 434=12, 467=12, 500=12, 534=100", + "videoRecordingStart": 866 + }, + "dn_chrome_cable": { + "FirstVisualChange": 400, + "LastVisualChange": 2467, + "SpeedIndex": 2145, + "PerceptualSpeedIndex": 1139, + "PerceptualSpeedIndexProgress": "0=0, 400=35, 434=36, 467=37, 500=38, 534=39, 567=40, 600=41, 634=42, 667=43, 700=44, 734=46, 767=47, 800=48, 834=49, 867=50, 900=51, 934=52, 967=53, 1000=54, 1034=55, 1067=56, 1100=57, 1134=59, 1167=60, 1200=61, 1234=62, 1267=63, 1567=73, 1600=74, 1634=75, 1667=76, 1700=77, 1734=78, 1767=79, 1800=80, 1834=81, 1867=82, 1900=83, 1934=84, 1967=85, 2000=86, 2034=87, 2067=88, 2100=89, 2134=90, 2167=91, 2200=92, 2234=93, 2267=94, 2300=95, 2334=96, 2367=97, 2400=98, 2434=99, 2467=100", + "ContentfulSpeedIndex": 1235, + "ContentfulSpeedIndexProgress": "0=0, 400=32, 434=33, 467=34, 500=35, 534=36, 567=38, 600=39, 634=40, 667=41, 700=42, 734=43, 767=44, 800=46, 834=47, 867=48, 900=49, 934=50, 967=51, 1000=52, 1034=54, 1067=55, 1100=56, 1134=57, 1167=58, 1200=59, 1234=60, 1267=61, 1567=72, 1600=73, 1634=74, 1667=75, 1700=76, 1734=77, 1767=78, 1800=79, 1834=80, 1867=81, 1900=82, 1934=84, 1967=85, 2000=86, 2034=87, 2067=88, 2100=89, 2134=90, 2167=91, 2200=92, 2234=93, 2267=94, 2300=95, 2334=96, 2367=97, 2400=98, 2434=100, 2467=100", + "VisualProgress": "0=0, 400=5, 434=15, 467=15, 500=15, 534=15, 567=15, 600=15, 634=15, 667=15, 700=15, 734=15, 767=15, 800=15, 834=15, 867=15, 900=15, 934=16, 967=16, 1000=16, 1034=16, 1067=16, 1100=16, 1134=16, 1167=16, 1200=16, 1234=16, 1267=16, 1567=16, 1600=16, 1634=15, 1667=15, 1700=16, 1734=16, 1767=16, 1800=16, 1834=16, 1867=16, 1900=16, 1934=16, 1967=16, 2000=16, 2034=16, 2067=16, 2100=16, 2134=16, 2167=16, 2200=16, 2234=16, 2267=16, 2300=16, 2334=16, 2367=16, 2400=16, 2434=16, 2467=100", + "videoRecordingStart": 866 + }, + "duckduckgo_firefox": { + "FirstVisualChange": 400, + "LastVisualChange": 9166, + "SpeedIndex": 561, + "PerceptualSpeedIndex": 414, + "PerceptualSpeedIndexProgress": "0=0, 400=96, 433=96, 466=97, 500=97, 533=97, 566=98, 600=98, 633=98, 666=98, 700=98, 733=98, 766=98, 800=98, 833=98, 866=98, 900=98, 933=98, 966=98, 1000=98, 1033=98, 1066=98, 1100=98, 1133=98, 1166=98, 1200=98, 1233=98, 1700=98, 1733=98, 1766=99, 1800=99, 1833=99, 1866=99, 1900=99, 1933=99, 1966=99, 2000=99, 2033=99, 2066=99, 2100=99, 2133=99, 2166=99, 2200=99, 2233=99, 2266=99, 2300=99, 2333=99, 2366=99, 2400=99, 2433=99, 2466=99, 2500=99, 2533=99, 2566=99, 2600=99, 2633=99, 2666=99, 2700=99, 2733=99, 2766=99, 2800=99, 2833=99, 2866=99, 2900=99, 2933=99, 2966=99, 3000=99, 3033=99, 3066=99, 3100=99, 3133=99, 3166=99, 3200=99, 3233=99, 3266=99, 3300=99, 3333=99, 3366=99, 3400=99, 3433=99, 3466=99, 3500=99, 3533=99, 3566=99, 3600=99, 3633=99, 3666=99, 3700=99, 3733=99, 3766=99, 3800=99, 3833=99, 7433=99, 7466=99, 7500=99, 7533=99, 7566=99, 7600=99, 7633=99, 7666=99, 7700=99, 7733=99, 7766=99, 7800=99, 7833=99, 7866=99, 7900=99, 7933=99, 7966=99, 8000=99, 8033=99, 8066=99, 8100=99, 8133=99, 8166=99, 8200=99, 8233=99, 8266=99, 8300=99, 8333=99, 8366=99, 8400=99, 8433=99, 8466=99, 8500=99, 8533=99, 8566=99, 8600=99, 8633=99, 8666=99, 8700=99, 8733=99, 8766=99, 8800=99, 8833=99, 8866=99, 8900=99, 8933=99, 8966=100, 9000=100, 9033=100, 9066=100, 9100=100, 9133=100, 9166=100", + "ContentfulSpeedIndex": 491, + "ContentfulSpeedIndexProgress": "0=0, 400=81, 433=82, 466=83, 500=83, 533=84, 566=84, 600=85, 633=85, 666=85, 700=85, 733=85, 766=85, 800=85, 833=85, 866=85, 900=85, 933=85, 966=85, 1000=85, 1033=86, 1066=86, 1100=86, 1133=86, 1166=86, 1200=86, 1233=86, 1700=87, 1733=87, 1766=87, 1800=87, 1833=87, 1866=87, 1900=87, 1933=88, 1966=88, 2000=88, 2033=88, 2066=88, 2100=88, 2133=88, 2166=88, 2200=88, 2233=89, 2266=89, 2300=89, 2333=89, 2366=89, 2400=89, 2433=89, 2466=89, 2500=89, 2533=89, 2566=89, 2600=89, 2633=89, 2666=89, 2700=89, 2733=89, 2766=89, 2800=90, 2833=90, 2866=90, 2900=90, 2933=90, 2966=90, 3000=90, 3033=90, 3066=90, 3100=90, 3133=90, 3166=90, 3200=90, 3233=90, 3266=90, 3300=91, 3333=91, 3366=91, 3400=91, 3433=91, 3466=91, 3500=91, 3533=91, 3566=91, 3600=91, 3633=91, 3666=92, 3700=92, 3733=92, 3766=92, 3800=92, 3833=92, 7433=96, 7466=96, 7500=96, 7533=96, 7566=96, 7600=96, 7633=96, 7666=96, 7700=96, 7733=96, 7766=97, 7800=97, 7833=97, 7866=97, 7900=97, 7933=97, 7966=97, 8000=97, 8033=97, 8066=97, 8100=97, 8133=97, 8166=98, 8200=98, 8233=98, 8266=98, 8300=98, 8333=98, 8366=98, 8400=98, 8433=98, 8466=98, 8500=98, 8533=98, 8566=98, 8600=98, 8633=98, 8666=98, 8700=99, 8733=99, 8766=99, 8800=99, 8833=99, 8866=99, 8900=99, 8933=99, 8966=99, 9000=99, 9033=99, 9066=99, 9100=99, 9133=99, 9166=100", + "VisualProgress": "0=0, 400=96, 433=96, 466=96, 500=96, 533=96, 566=96, 600=98, 633=98, 666=98, 700=98, 733=98, 766=98, 800=98, 833=98, 866=98, 900=98, 933=98, 966=98, 1000=98, 1033=98, 1066=98, 1100=98, 1133=98, 1166=98, 1200=98, 1233=98, 1700=98, 1733=98, 1766=98, 1800=98, 1833=98, 1866=98, 1900=98, 1933=98, 1966=98, 2000=98, 2033=98, 2066=98, 2100=98, 2133=98, 2166=98, 2200=98, 2233=98, 2266=98, 2300=98, 2333=98, 2366=98, 2400=98, 2433=98, 2466=98, 2500=98, 2533=98, 2566=98, 2600=98, 2633=98, 2666=98, 2700=98, 2733=98, 2766=98, 2800=98, 2833=98, 2866=98, 2900=98, 2933=98, 2966=98, 3000=98, 3033=98, 3066=98, 3100=98, 3133=98, 3166=98, 3200=98, 3233=98, 3266=98, 3300=98, 3333=98, 3366=98, 3400=98, 3433=98, 3466=98, 3500=98, 3533=98, 3566=98, 3600=98, 3633=98, 3666=98, 3700=98, 3733=98, 3766=98, 3800=98, 3833=98, 7433=99, 7466=99, 7500=99, 7533=99, 7566=99, 7600=99, 7633=99, 7666=99, 7700=99, 7733=99, 7766=99, 7800=99, 7833=99, 7866=99, 7900=99, 7933=99, 7966=99, 8000=99, 8033=99, 8066=99, 8100=99, 8133=99, 8166=99, 8200=99, 8233=99, 8266=99, 8300=99, 8333=99, 8366=99, 8400=99, 8433=99, 8466=99, 8500=99, 8533=99, 8566=99, 8600=99, 8633=99, 8666=99, 8700=99, 8733=99, 8766=99, 8800=99, 8833=99, 8866=99, 8900=99, 8933=99, 8966=99, 9000=99, 9033=99, 9066=99, 9100=99, 9133=99, 9166=100", + "videoRecordingStart": 900 + }, + "github_firefox": { + "FirstVisualChange": 866, + "LastVisualChange": 4066, + "SpeedIndex": 1214, + "PerceptualSpeedIndex": 936, + "PerceptualSpeedIndexProgress": "0=0, 866=92, 900=93, 933=94, 966=94, 1000=95, 1033=95, 1066=95, 1100=95, 1133=95, 1166=95, 1200=95, 1233=95, 1266=96, 1300=96, 1333=96, 1366=96, 1400=96, 1433=96, 1466=96, 1500=96, 1533=96, 1566=97, 1600=97, 1633=97, 1666=97, 1700=97, 1733=97, 1766=97, 1800=97, 1833=97, 1866=97, 1900=98, 1933=98, 1966=98, 2000=98, 2033=98, 2066=98, 2100=98, 2133=98, 2166=98, 2200=98, 2233=98, 2266=98, 2300=98, 2333=99, 2366=99, 2400=99, 2433=99, 2466=99, 2500=99, 2533=99, 2566=99, 2600=99, 2633=99, 2666=99, 2700=99, 2733=99, 2766=99, 2800=99, 2833=99, 2866=99, 2900=99, 2933=99, 2966=99, 3000=99, 3033=99, 3066=99, 3100=99, 3133=99, 3166=99, 3200=99, 3233=99, 3266=99, 3300=99, 3333=99, 3366=99, 3400=99, 3433=99, 3466=99, 3500=99, 3533=100, 3566=100, 3600=100, 3633=100, 3666=100, 3700=100, 3733=100, 3766=100, 3800=100, 3833=100, 3866=100, 3900=100, 3933=100, 3966=100, 4000=100, 4033=100, 4066=100", + "ContentfulSpeedIndex": 931, + "ContentfulSpeedIndexProgress": "0=0, 866=93, 900=96, 933=96, 966=96, 1000=96, 1033=96, 1066=96, 1100=96, 1133=96, 1166=96, 1200=96, 1233=96, 1266=96, 1300=97, 1333=97, 1366=97, 1400=97, 1433=97, 1466=97, 1500=97, 1533=97, 1566=97, 1600=97, 1633=97, 1666=97, 1700=98, 1733=98, 1766=98, 1800=98, 1833=98, 1866=98, 1900=98, 1933=98, 1966=98, 2000=98, 2033=98, 2066=98, 2100=98, 2133=98, 2166=99, 2200=99, 2233=99, 2266=99, 2300=99, 2333=99, 2366=99, 2400=99, 2433=99, 2466=99, 2500=99, 2533=99, 2566=99, 2600=99, 2633=99, 2666=99, 2700=99, 2733=99, 2766=99, 2800=99, 2833=99, 2866=99, 2900=99, 2933=99, 2966=99, 3000=99, 3033=99, 3066=99, 3100=99, 3133=99, 3166=99, 3200=99, 3233=99, 3266=99, 3300=99, 3333=99, 3366=99, 3400=99, 3433=99, 3466=99, 3500=99, 3533=99, 3566=99, 3600=99, 3633=99, 3666=99, 3700=100, 3733=100, 3766=100, 3800=100, 3833=100, 3866=100, 3900=100, 3933=100, 3966=100, 4000=100, 4033=100, 4066=100", + "VisualProgress": "0=0, 866=8, 900=10, 933=43, 966=45, 1000=80, 1033=80, 1066=80, 1100=80, 1133=80, 1166=80, 1200=80, 1233=80, 1266=80, 1300=80, 1333=80, 1366=81, 1400=81, 1433=82, 1466=82, 1500=83, 1533=82, 1566=83, 1600=83, 1633=84, 1666=84, 1700=85, 1733=85, 1766=86, 1800=86, 1833=87, 1866=87, 1900=87, 1933=88, 1966=88, 2000=89, 2033=89, 2066=90, 2100=90, 2133=91, 2166=91, 2200=91, 2233=92, 2266=92, 2300=93, 2333=93, 2366=94, 2400=94, 2433=94, 2466=94, 2500=95, 2533=95, 2566=95, 2600=95, 2633=96, 2666=96, 2700=96, 2733=96, 2766=96, 2800=97, 2833=97, 2866=97, 2900=97, 2933=97, 2966=97, 3000=97, 3033=98, 3066=98, 3100=98, 3133=98, 3166=98, 3200=98, 3233=98, 3266=98, 3300=98, 3333=98, 3366=98, 3400=98, 3433=98, 3466=98, 3500=98, 3533=98, 3566=98, 3600=98, 3633=98, 3666=99, 3700=99, 3733=98, 3766=99, 3800=99, 3833=99, 3866=99, 3900=99, 3933=99, 3966=99, 4000=99, 4033=99, 4066=100", + "videoRecordingStart": 900 + }, + "google_chrome": { + "FirstVisualChange": 800, + "LastVisualChange": 800, + "SpeedIndex": 800, + "PerceptualSpeedIndex": 800, + "PerceptualSpeedIndexProgress": "0=0, 800=100", + "ContentfulSpeedIndex": 800, + "ContentfulSpeedIndexProgress": "0=0, 800=100", + "VisualProgress": "0=0, 800=100", + "videoRecordingStart": 866 + }, + "reddit_chrome": { + "FirstVisualChange": 534, + "LastVisualChange": 1400, + "SpeedIndex": 1200, + "PerceptualSpeedIndex": 1050, + "PerceptualSpeedIndexProgress": "0=0, 534=50, 567=52, 600=54, 634=57, 667=59, 700=61, 734=63, 767=65, 800=67, 834=69, 867=71, 900=73, 934=75, 967=77, 1000=79, 1034=81, 1067=83, 1100=84, 1134=86, 1167=88, 1200=89, 1234=91, 1267=93, 1300=94, 1334=96, 1367=98, 1400=100", + "ContentfulSpeedIndex": 1200, + "ContentfulSpeedIndexProgress": "0=0, 534=44, 567=47, 600=49, 634=52, 667=55, 700=58, 734=61, 767=63, 800=66, 834=69, 867=72, 900=74, 934=77, 967=79, 1000=81, 1034=83, 1067=85, 1100=87, 1134=89, 1167=90, 1200=92, 1234=93, 1267=95, 1300=96, 1334=98, 1367=100, 1400=100", + "VisualProgress": "0=0, 534=0, 567=0, 600=0, 634=0, 667=0, 700=0, 734=0, 767=0, 800=0, 834=0, 867=0, 900=0, 934=0, 967=44, 1000=44, 1034=44, 1067=44, 1100=43, 1134=43, 1167=48, 1200=48, 1234=48, 1267=48, 1300=48, 1334=48, 1367=48, 1400=100", + "videoRecordingStart": 866 + }, + "sitespeed_android": { + "FirstVisualChange": 470, + "LastVisualChange": 893, + "SpeedIndex": 551, + "PerceptualSpeedIndex": 527, + "PerceptualSpeedIndexProgress": "0=0, 470=89, 482=90, 563=98, 585=99, 619=100, 650=100, 662=100, 796=100, 815=100, 846=100, 862=100, 879=100, 893=100", + "ContentfulSpeedIndex": 505, + "ContentfulSpeedIndexProgress": "0=0, 470=93, 482=95, 563=99, 585=100, 619=100, 650=100, 662=100, 796=100, 815=100, 846=100, 862=100, 879=100, 893=100", + "VisualProgress": "0=0, 470=23, 482=23, 563=83, 585=97, 619=98, 650=98, 662=98, 796=98, 815=98, 846=99, 862=99, 879=99, 893=100", + "videoRecordingStart": 1702 + }, + "wikipedia_android": { + "FirstVisualChange": 801, + "LastVisualChange": 1079, + "SpeedIndex": 822, + "PerceptualSpeedIndex": 816, + "PerceptualSpeedIndexProgress": "0=0, 801=98, 818=98, 848=98, 1015=100, 1036=100, 1057=100, 1079=100", + "ContentfulSpeedIndex": 808, + "ContentfulSpeedIndexProgress": "0=0, 801=99, 818=99, 848=100, 1015=100, 1036=100, 1057=100, 1079=100", + "VisualProgress": "0=0, 801=91, 818=90, 848=90, 1015=99, 1036=99, 1057=99, 1079=100", + "videoRecordingStart": 1693 + }, + "wikipedia_chrome": { + "FirstVisualChange": 234, + "LastVisualChange": 9667, + "SpeedIndex": 1105, + "PerceptualSpeedIndex": 296, + "PerceptualSpeedIndexProgress": "0=0, 234=79, 267=79, 300=79, 334=79, 367=79, 400=79, 434=80, 467=80, 500=80, 534=80, 567=80, 600=80, 634=80, 667=80, 700=80, 734=80, 767=81, 800=81, 834=81, 867=81, 900=81, 934=81, 967=81, 1000=81, 1034=81, 1067=81, 1100=81, 1134=81, 1167=81, 1200=81, 1234=82, 1267=82, 1367=82, 1400=82, 1434=82, 1467=82, 1500=82, 1534=82, 1567=82, 1600=82, 1634=82, 1667=82, 1700=83, 1734=83, 1767=83, 1800=83, 1834=83, 1867=83, 1900=83, 1934=83, 1967=83, 2000=83, 2034=83, 2067=83, 2100=83, 2134=83, 2167=83, 2200=83, 2234=83, 2267=83, 2300=84, 2334=84, 2367=84, 2400=84, 2434=84, 2467=84, 2500=84, 2534=84, 2567=84, 2600=84, 2634=84, 2667=84, 2700=85, 2734=85, 2767=85, 2800=85, 2834=85, 2867=85, 2900=85, 2934=85, 2967=85, 3000=85, 3034=85, 3067=85, 3100=85, 3134=85, 3167=86, 3200=86, 3234=86, 3267=86, 3300=86, 3334=86, 3367=86, 3400=86, 3434=86, 3467=86, 3500=86, 3600=87, 3634=87, 3667=87, 3700=87, 3734=87, 3767=87, 3800=87, 3834=87, 3867=87, 3900=87, 3934=87, 3967=87, 4000=87, 4034=87, 4067=87, 4100=87, 4134=87, 4167=88, 4200=88, 4234=88, 4267=88, 4300=88, 4334=88, 4367=88, 4400=88, 4434=88, 4467=88, 4500=88, 4534=88, 4567=88, 4600=89, 4634=89, 4667=89, 4700=89, 4734=89, 4767=89, 4800=89, 4834=89, 4867=89, 4900=89, 4934=89, 4967=89, 5000=89, 5034=89, 5067=90, 5100=90, 5134=90, 5167=90, 5200=90, 5234=90, 5267=90, 5300=90, 5334=90, 5367=90, 5400=90, 5434=90, 5467=91, 5500=91, 5534=91, 5567=91, 5600=91, 5634=91, 5667=91, 5700=91, 5734=91, 5834=91, 5867=91, 5900=91, 5934=91, 5967=91, 6000=91, 6034=91, 6067=91, 6100=92, 6134=92, 6167=92, 6200=92, 6234=92, 6267=92, 6300=92, 6334=92, 6367=92, 6400=92, 6434=92, 6467=92, 6500=92, 6534=93, 6567=93, 6600=93, 6634=93, 6667=93, 6700=93, 6734=93, 6767=93, 6800=93, 6834=93, 6867=93, 6900=93, 6934=93, 6967=93, 7000=94, 7034=94, 7067=94, 7100=94, 7134=94, 7167=94, 7200=94, 7234=94, 7267=94, 7300=94, 7334=94, 7367=94, 7400=95, 7434=95, 7467=95, 7500=95, 7534=95, 7567=95, 7600=95, 7634=95, 7667=95, 7700=95, 7734=95, 7767=95, 7800=95, 7834=95, 7867=95, 7900=95, 7934=95, 7967=95, 8067=96, 8100=96, 8134=96, 8167=96, 8200=96, 8234=96, 8267=96, 8300=96, 8334=96, 8367=96, 8400=96, 8434=96, 8467=97, 8500=97, 8534=97, 8567=97, 8600=97, 8634=97, 8667=97, 8700=97, 8734=97, 8767=97, 8800=97, 8834=97, 8867=97, 8900=97, 8934=98, 8967=98, 9000=98, 9034=98, 9067=98, 9100=98, 9134=98, 9167=98, 9200=98, 9234=98, 9267=98, 9300=98, 9334=99, 9367=99, 9400=99, 9434=99, 9467=99, 9500=99, 9534=99, 9567=99, 9600=99, 9634=99, 9667=100", + "ContentfulSpeedIndex": 387, + "ContentfulSpeedIndexProgress": "0=0, 234=60, 267=61, 300=63, 334=65, 367=66, 400=68, 434=70, 467=70, 500=70, 534=70, 567=70, 600=70, 634=70, 667=70, 700=70, 734=70, 767=71, 800=71, 834=71, 867=71, 900=71, 934=71, 967=71, 1000=71, 1034=71, 1067=72, 1100=72, 1134=72, 1167=72, 1200=72, 1234=72, 1267=72, 1367=73, 1400=73, 1434=73, 1467=73, 1500=73, 1534=73, 1567=73, 1600=73, 1634=73, 1667=74, 1700=74, 1734=74, 1767=74, 1800=74, 1834=74, 1867=75, 1900=75, 1934=75, 1967=75, 2000=75, 2034=75, 2067=75, 2100=75, 2134=75, 2167=76, 2200=76, 2234=76, 2267=76, 2300=76, 2334=76, 2367=76, 2400=76, 2434=76, 2467=76, 2500=76, 2534=76, 2567=77, 2600=77, 2634=77, 2667=77, 2700=77, 2734=77, 2767=77, 2800=77, 2834=77, 2867=77, 2900=77, 2934=78, 2967=78, 3000=78, 3034=78, 3067=78, 3100=78, 3134=78, 3167=78, 3200=79, 3234=79, 3267=79, 3300=79, 3334=79, 3367=79, 3400=79, 3434=79, 3467=79, 3500=79, 3600=80, 3634=80, 3667=80, 3700=80, 3734=80, 3767=80, 3800=81, 3834=81, 3867=81, 3900=81, 3934=81, 3967=81, 4000=81, 4034=81, 4067=81, 4100=81, 4134=82, 4167=82, 4200=82, 4234=82, 4267=82, 4300=82, 4334=82, 4367=82, 4400=82, 4434=82, 4467=82, 4500=82, 4534=82, 4567=82, 4600=82, 4634=82, 4667=83, 4700=83, 4734=83, 4767=83, 4800=83, 4834=83, 4867=83, 4900=83, 4934=84, 4967=84, 5000=84, 5034=84, 5067=84, 5100=84, 5134=84, 5167=85, 5200=85, 5234=85, 5267=85, 5300=85, 5334=85, 5367=85, 5400=85, 5434=85, 5467=85, 5500=85, 5534=86, 5567=86, 5600=86, 5634=86, 5667=86, 5700=86, 5734=86, 5834=87, 5867=87, 5900=87, 5934=87, 5967=87, 6000=87, 6034=87, 6067=87, 6100=88, 6134=88, 6167=88, 6200=88, 6234=88, 6267=88, 6300=88, 6334=88, 6367=88, 6400=88, 6434=88, 6467=88, 6500=88, 6534=88, 6567=88, 6600=89, 6634=89, 6667=89, 6700=89, 6734=89, 6767=89, 6800=89, 6834=89, 6867=90, 6900=90, 6934=90, 6967=90, 7000=90, 7034=90, 7067=90, 7100=91, 7134=91, 7167=91, 7200=91, 7234=91, 7267=91, 7300=91, 7334=91, 7367=91, 7400=92, 7434=92, 7467=92, 7500=92, 7534=92, 7567=92, 7600=92, 7634=93, 7667=93, 7700=93, 7734=93, 7767=93, 7800=93, 7834=94, 7867=94, 7900=94, 7934=94, 7967=94, 8067=94, 8100=94, 8134=94, 8167=95, 8200=95, 8234=95, 8267=95, 8300=95, 8334=95, 8367=95, 8400=95, 8434=95, 8467=95, 8500=95, 8534=95, 8567=95, 8600=95, 8634=95, 8667=96, 8700=96, 8734=96, 8767=96, 8800=96, 8834=96, 8867=96, 8900=97, 8934=97, 8967=97, 9000=97, 9034=97, 9067=97, 9100=97, 9134=98, 9167=98, 9200=98, 9234=98, 9267=98, 9300=98, 9334=98, 9367=98, 9400=98, 9434=99, 9467=99, 9500=99, 9534=99, 9567=99, 9600=99, 9634=100, 9667=100", + "VisualProgress": "0=0, 234=83, 267=81, 300=82, 334=82, 367=83, 400=83, 434=83, 467=89, 500=89, 534=89, 567=89, 600=89, 634=89, 667=89, 700=89, 734=89, 767=89, 800=89, 834=89, 867=89, 900=89, 934=89, 967=89, 1000=89, 1034=89, 1067=89, 1100=89, 1134=89, 1167=89, 1200=89, 1234=89, 1267=89, 1367=89, 1400=89, 1434=89, 1467=89, 1500=89, 1534=89, 1567=89, 1600=89, 1634=89, 1667=89, 1700=89, 1734=89, 1767=89, 1800=89, 1834=89, 1867=89, 1900=89, 1934=89, 1967=89, 2000=89, 2034=90, 2067=90, 2100=90, 2134=90, 2167=90, 2200=89, 2234=89, 2267=89, 2300=89, 2334=89, 2367=89, 2400=89, 2434=89, 2467=89, 2500=89, 2534=89, 2567=89, 2600=89, 2634=89, 2667=89, 2700=89, 2734=89, 2767=89, 2800=89, 2834=89, 2867=89, 2900=89, 2934=89, 2967=89, 3000=89, 3034=89, 3067=89, 3100=89, 3134=89, 3167=89, 3200=89, 3234=89, 3267=89, 3300=89, 3334=89, 3367=89, 3400=89, 3434=89, 3467=89, 3500=89, 3600=89, 3634=89, 3667=89, 3700=89, 3734=89, 3767=89, 3800=89, 3834=89, 3867=89, 3900=89, 3934=89, 3967=89, 4000=90, 4034=89, 4067=89, 4100=90, 4134=90, 4167=90, 4200=90, 4234=89, 4267=89, 4300=89, 4334=89, 4367=89, 4400=89, 4434=89, 4467=89, 4500=89, 4534=89, 4567=89, 4600=89, 4634=89, 4667=89, 4700=89, 4734=89, 4767=89, 4800=89, 4834=89, 4867=89, 4900=89, 4934=89, 4967=89, 5000=89, 5034=89, 5067=89, 5100=89, 5134=89, 5167=89, 5200=89, 5234=89, 5267=89, 5300=89, 5334=89, 5367=90, 5400=89, 5434=89, 5467=89, 5500=89, 5534=89, 5567=89, 5600=89, 5634=89, 5667=89, 5700=89, 5734=89, 5834=89, 5867=89, 5900=89, 5934=90, 5967=89, 6000=89, 6034=89, 6067=90, 6100=90, 6134=90, 6167=90, 6200=89, 6234=89, 6267=89, 6300=89, 6334=89, 6367=89, 6400=89, 6434=89, 6467=89, 6500=89, 6534=89, 6567=89, 6600=89, 6634=89, 6667=89, 6700=89, 6734=89, 6767=89, 6800=89, 6834=89, 6867=89, 6900=89, 6934=89, 6967=89, 7000=89, 7034=89, 7067=89, 7100=89, 7134=89, 7167=89, 7200=89, 7234=89, 7267=89, 7300=89, 7334=89, 7367=89, 7400=89, 7434=89, 7467=96, 7500=97, 7534=97, 7567=97, 7600=97, 7634=97, 7667=97, 7700=97, 7734=97, 7767=97, 7800=97, 7834=97, 7867=97, 7900=97, 7934=97, 7967=97, 8067=97, 8100=97, 8134=97, 8167=97, 8200=97, 8234=97, 8267=97, 8300=97, 8334=97, 8367=97, 8400=97, 8434=97, 8467=97, 8500=97, 8534=97, 8567=97, 8600=97, 8634=97, 8667=97, 8700=97, 8734=97, 8767=97, 8800=97, 8834=97, 8867=97, 8900=97, 8934=97, 8967=97, 9000=97, 9034=97, 9067=97, 9100=97, 9134=97, 9167=97, 9200=97, 9234=97, 9267=97, 9300=97, 9334=97, 9367=97, 9400=97, 9434=97, 9467=97, 9500=97, 9534=97, 9567=97, 9600=97, 9634=97, 9667=100", + "videoRecordingStart": 866 + }, + "youtube_chrome": { + "FirstVisualChange": 234, + "LastVisualChange": 934, + "SpeedIndex": 859, + "PerceptualSpeedIndex": 479, + "PerceptualSpeedIndexProgress": "0=0, 234=48, 267=51, 300=55, 334=58, 367=62, 400=65, 434=68, 467=72, 500=75, 534=78, 567=82, 600=85, 634=88, 667=92, 700=94, 734=97, 767=98, 800=99, 834=99, 867=99, 900=100, 934=100", + "ContentfulSpeedIndex": 622, + "ContentfulSpeedIndexProgress": "0=0, 234=37, 267=41, 300=45, 334=49, 367=53, 400=57, 434=61, 467=65, 500=69, 534=73, 567=77, 600=81, 634=85, 667=90, 700=95, 734=97, 767=97, 800=98, 834=99, 867=100, 900=100, 934=100", + "VisualProgress": "0=0, 234=6, 267=6, 300=6, 334=6, 367=6, 400=6, 434=6, 467=6, 500=6, 534=6, 567=6, 600=6, 634=6, 667=2, 700=1, 734=17, 767=19, 800=20, 834=22, 867=29, 900=36, 934=100", + "videoRecordingStart": 866 + } +} \ No newline at end of file diff --git a/visualmetrics/test_videos/github_firefox.mp4 b/visualmetrics/test_videos/github_firefox.mp4 new file mode 100644 index 000000000..402ec34ea Binary files /dev/null and b/visualmetrics/test_videos/github_firefox.mp4 differ diff --git a/visualmetrics/test_videos/google_chrome.mp4 b/visualmetrics/test_videos/google_chrome.mp4 new file mode 100644 index 000000000..22d8745c2 Binary files /dev/null and b/visualmetrics/test_videos/google_chrome.mp4 differ diff --git a/visualmetrics/test_videos/reddit_chrome.mp4 b/visualmetrics/test_videos/reddit_chrome.mp4 new file mode 100644 index 000000000..cc0d61f56 Binary files /dev/null and b/visualmetrics/test_videos/reddit_chrome.mp4 differ diff --git a/visualmetrics/test_videos/sitespeed_android.mp4 b/visualmetrics/test_videos/sitespeed_android.mp4 new file mode 100644 index 000000000..2154e03f5 Binary files /dev/null and b/visualmetrics/test_videos/sitespeed_android.mp4 differ diff --git a/visualmetrics/test_videos/wikipedia_android.mp4 b/visualmetrics/test_videos/wikipedia_android.mp4 new file mode 100644 index 000000000..68511ae92 Binary files /dev/null and b/visualmetrics/test_videos/wikipedia_android.mp4 differ diff --git a/visualmetrics/test_videos/wikipedia_chrome.mp4 b/visualmetrics/test_videos/wikipedia_chrome.mp4 new file mode 100644 index 000000000..fa8add16c Binary files /dev/null and b/visualmetrics/test_videos/wikipedia_chrome.mp4 differ diff --git a/visualmetrics/test_videos/youtube_chrome.mp4 b/visualmetrics/test_videos/youtube_chrome.mp4 new file mode 100644 index 000000000..74b92ac1b Binary files /dev/null and b/visualmetrics/test_videos/youtube_chrome.mp4 differ diff --git a/visualmetrics/test_visual_metrics_regression.py b/visualmetrics/test_visual_metrics_regression.py new file mode 100644 index 000000000..648d641b3 --- /dev/null +++ b/visualmetrics/test_visual_metrics_regression.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +""" +Regression tests for the visual metrics Python script used by browsertime. + +Ensures that changes to visualmetrics-portable.py do not accidentally +alter the calculated metrics (Speed Index, Perceptual Speed Index, etc.). +Each test runs the script on a pre-recorded browser video and asserts +that every metric exactly matches a known golden value. + +The test videos are recorded from real websites using browsertime across +different configurations: + - Desktop Chrome and Firefox (macOS screen recording) + - Desktop with cable-throttled network (5/1 Mbps, 28ms RTT) + - Android device (Samsung A51, screen recording via adb) + +Golden values are stored in test_videos/expected_metrics.json and should +be regenerated with --generate whenever metrics change intentionally. + +Usage: + python test_visual_metrics_regression.py # Run all tests + python test_visual_metrics_regression.py -v # Verbose output + +To regenerate expected metrics after intentional changes: + python test_visual_metrics_regression.py --generate +""" +import json +import os +import subprocess +import sys +import time +import unittest + +HERE = os.path.dirname(os.path.abspath(__file__)) +VIDEO_DIR = os.path.join(HERE, "test_videos") +SCRIPT = os.path.join(HERE, "visualmetrics-portable.py") +EXPECTED_FILE = os.path.join(VIDEO_DIR, "expected_metrics.json") +PYTHON = os.environ.get("PYTHON", sys.executable) + +# Same arguments that browsertime passes to the script in production +# (see lib/video/postprocessing/visualmetrics/visualMetrics.js) +SCRIPT_ARGS = [ + "--orange", + "--force", + "--renderignore", "5", + "--json", + "--viewport", + "--viewportretries", "60", + "--viewportminheight", "100", + "--viewportminwidth", "100", + "--perceptual", + "--contentful", + "-vvv", +] + +# Every metric the script outputs that we verify +ALL_METRICS = [ + "FirstVisualChange", + "LastVisualChange", + "SpeedIndex", + "PerceptualSpeedIndex", + "PerceptualSpeedIndexProgress", + "ContentfulSpeedIndex", + "ContentfulSpeedIndexProgress", + "VisualProgress", + "videoRecordingStart", +] + + +def run_script(video_path): + """Run the visual metrics script on a video and return parsed JSON metrics.""" + logfile = video_path + ".test.log" + args = [PYTHON, SCRIPT, "--video", video_path, "--logfile", logfile] + SCRIPT_ARGS + + result = subprocess.run(args, capture_output=True, text=True, timeout=300) + + if result.returncode != 0: + raise RuntimeError( + f"Script failed on {os.path.basename(video_path)} " + f"(exit {result.returncode}):\n{result.stderr[-500:]}" + ) + + # JSON is the last line of stdout (ffmpeg output may precede it) + lines = result.stdout.strip().split("\n") + return json.loads(lines[-1]) + + +def load_expected(): + """Load expected metrics from the golden values file.""" + with open(EXPECTED_FILE) as f: + return json.load(f) + + +def generate_expected(): + """Re-generate expected metrics by running the script on all videos.""" + import glob + + videos = sorted(glob.glob(os.path.join(VIDEO_DIR, "*.mp4"))) + expected = {} + + for video in videos: + name = os.path.basename(video).replace(".mp4", "") + print(f" Generating {name}...", end=" ", flush=True) + start = time.perf_counter() + try: + metrics = run_script(video) + if metrics.get("SpeedIndex", 0) == 0: + print(f"SKIPPED (zero metrics)") + continue + expected[name] = metrics + elapsed = time.perf_counter() - start + print(f"SI={metrics['SpeedIndex']} ({elapsed:.1f}s)") + except Exception as e: + print(f"FAILED: {e}") + + with open(EXPECTED_FILE, "w") as f: + json.dump(expected, f, indent=2) + + print(f"\nSaved {len(expected)} entries to {EXPECTED_FILE}") + + +def make_test(video_name): + """Create a test method for a given video.""" + video_path = os.path.join(VIDEO_DIR, video_name + ".mp4") + + def test_method(self): + if not os.path.isfile(video_path): + self.skipTest(f"Video not found: {video_name}.mp4") + + expected = self._expected.get(video_name) + if expected is None: + self.skipTest(f"No expected metrics for {video_name}") + + start = time.perf_counter() + actual = run_script(video_path) + elapsed = time.perf_counter() - start + + print(f"\n {video_name}: SI={actual.get('SpeedIndex')} ({elapsed:.1f}s)") + + # Assert every expected metric matches + for metric in ALL_METRICS: + if metric in expected: + self.assertEqual( + actual.get(metric), + expected[metric], + f"{video_name}: {metric} mismatch\n" + f" expected: {expected[metric]}\n" + f" actual: {actual.get(metric)}", + ) + + # No unexpected missing metrics + for key in expected: + self.assertIn( + key, actual, + f"{video_name}: metric '{key}' missing from output", + ) + + test_method.__doc__ = f"Regression test: {video_name}" + return test_method + + +class TestVisualMetricsRegression(unittest.TestCase): + """Run the visual metrics script on each video and compare against golden values.""" + + _expected = None + + @classmethod + def setUpClass(cls): + if not os.path.isfile(SCRIPT): + raise FileNotFoundError(f"Script not found: {SCRIPT}") + if not os.path.isfile(EXPECTED_FILE): + raise FileNotFoundError( + f"Expected metrics not found: {EXPECTED_FILE}\n" + f"Run with --generate to create them." + ) + cls._expected = load_expected() + + +# Each video is named {site}_{browser}[_{variant}].mp4 +# Recorded with: browsertime -n 1 --video --visualMetrics false +VIDEOS = [ + # Desktop Chrome (macOS) + "google_chrome", + "youtube_chrome", + "wikipedia_chrome", + "amazon_chrome", + "reddit_chrome", + "aftonbladet_chrome", + "dn_chrome", + # Desktop Firefox (macOS) + "github_firefox", + "apple_firefox", + "bing_firefox", + "duckduckgo_firefox", + "bbc_firefox", + "cnet_firefox", + # Desktop with cable throttle (5/1 Mbps, 28ms RTT) + "aftonbladet_chrome_cable", + "dn_chrome_cable", + "cnet_firefox_cable", + # Android Chrome (Samsung A51) + "wikipedia_android", + "aftonbladet_android", + "sitespeed_android", +] + +# One test method per video — each runs the script and asserts all metrics match +for _video in VIDEOS: + setattr(TestVisualMetricsRegression, f"test_{_video}", make_test(_video)) + + +if __name__ == "__main__": + if "--generate" in sys.argv: + sys.argv.remove("--generate") + print("Generating expected metrics...") + generate_expected() + else: + unittest.main(verbosity=2)