diff --git a/.gitattributes b/.gitattributes index c3cf27cad..35b817f6f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,5 @@ test/browser/media/hls/*.m3u8 text eol=lf test/browser/fixtures/hls-grouped.m3u8 text eol=lf test/browser/media/hls/*.mpegts binary +test/browser/media/*.m4a binary refactor/baselines/core-vendor/*.txt text eol=lf diff --git a/package.json b/package.json index 1000c8575..92b5b7398 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "ci:build": "yarn build:types && yarn build all && yarn build:i18n && yarn build:ts && yarn build:docs && yarn test:imports", "test:imports": "node --test test/esm.test.js test/i18n.test.js test/ssr.test.js", "typecheck": "node scripts/typecheck.mjs", - "test:unit": "node --test test/playback.test.js test/dash-control.test.js test/hls-control.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js", + "test:unit": "node --test test/playback.test.js test/dash-control.test.js test/hls-control.test.js test/audio-track.test.js test/public-behavior.test.js test/helpers.test.js test/chapter.test.js test/utils.test.js test/resource-scope.test.js test/instance-lifecycle.test.js test/options.test.js test/media-hosts.test.js test/plugins.test.js test/source.test.js test/playback-properties.test.js test/media-events.test.js test/template-resources.test.js test/core-vendor.test.js test/component-resources.test.js test/setting-model.test.js test/setting-layout.test.js test/setting-resources.test.js test/subtitle.test.js test/display-native.test.js test/display-video-fullscreen.test.js test/display-pip.test.js test/display-mini.test.js test/display-sizing.test.js test/display-orientation.test.js test/hotkey.test.js test/listener-registry.test.js test/global-events.test.js test/pointer-events.test.js test/gesture.test.js test/event-scheduling.test.js test/notice.test.js test/fast-forward.test.js test/auto-playback.test.js test/builtin-layers.test.js test/prompt-components.test.js test/screenshot.test.js test/thumbnails.test.js test/progress.test.js test/environment.test.js test/storage.test.js test/facade-properties.test.js test/dom-boundaries.test.js test/initialization.test.js test/entry.test.js test/accessibility-button.test.js test/accessibility-focus.test.js test/accessibility-slider.test.js", "test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", diff --git a/refactor/audio-validation.md b/refactor/audio-validation.md new file mode 100644 index 000000000..29d0a9665 --- /dev/null +++ b/refactor/audio-validation.md @@ -0,0 +1,61 @@ +# Audio Track 行为与媒体测试 + +PKG-AUDIO-02;公开来源见 [1.1.0 契约](baselines/audio-track-contract.md), +固定执行结果及失败保留见 [验证记录](baselines/audio-validation.json)。 + +## 已实现命令 + +```sh +node --test test/audio-track.test.js +yarn ci:check +yarn test:browser test/browser/audio-track.spec.js --trace on +``` + +Node 专项 38 项:源码和真实发布 main/legacy/module,初始化/延迟安装、暴露 audio、 +严格阈值、正负偏移、seek/播放前同步、playing 条件、waiting/pause、音量/静音/倍率、 +同/空/新 URL、三处 play 拒绝、销毁和多实例隔离。Audio 是记录调用的受控对象,不模拟解码。 +工厂输入跨 realm 检查使用冻结归档,源码使用既有 JS/TS loader,可随迁移继续回归。 + +真实浏览器最终 36 项通过,无重试、跳过:每引擎 8 项新旧核心/插件播放及失败恢复, +1 项原生 WAV 诊断、1 项旧插件空 src 销毁问题、2 项不同核心的原生暂停/结束缺陷观察。 +因此 36 通过不代表 36 项无缺陷的候选功能验收:9 项复现历史问题,3 项是原生能力诊断。 +旧核心固定 5.4.0、旧插件固定 1.1.0;候选来自源码构建,非隔离安装包。 + +播放证据包括主视频实际解码颜色、媒体时钟、AAC 音频加载/时钟、偏移 seek、倍率/音量、 +音频切源后的同一元素及同步、503 加载失败后换源恢复。公开 audio 的事件、状态、 +原始 warning、代码/媒体/核心产物指纹随测试附件保存。不声称已经测得扬声器输出或音画主观同步。 +Node 控制 waiting/playing 与 play 拒绝;实际浏览器网络缓冲/自动播放策略和移动环境由 05 补充。 + +## 样本与失败归因 + +test/browser/media/audio-tone.m4a 是本地生成的 16 秒 440 Hz 单声道 AAC。 +生成命令、FFmpeg 版本、ffprobe 及哈希见旁边 audio-tone.json,测试重验哈希。 +服务器沿用已有 GET/HEAD/Range,增加 audio/mp4 MIME;无外网音频依赖。 +WAV 诊断使用整数方波,完整参数/哈希冻结。直接原生 Audio(未创建 ArtPlayer)在 +Windows WebKit 也给出错误 4;AAC 矩阵通过不能覆盖该 WAV 或真实 Safari 的能力。 + +初轮 24 失败及后续诊断均保存,没有覆盖成绿灯: + +1. 测试先用了 currentTime setter;它不发 seek 事件。修正为已有公开 art.seek,未修改核心。 +2. 旧插件 src='' 后 readyState=0、paused=true,但 currentSrc 可能保留且 error=4。 + 正常基线清理检查属性/暂停/就绪状态,另立发布版缺陷断言,不把旧错误当作已修复。 +3. WAV 在 Windows WebKit 失败;用无播放器原生 Audio 对照隔离,并增加独立 AAC 测试输入。 +4. 最初 AAC route 固定返回 200 全文件,seek 返回 0;改用现有 Range 服务器,验证 seekable + 覆盖目标再 seek。没有增加超时或移除实际 seek 断言。 +5. Windows WebKit 视频尺寸可能反映布局,既有 browser/README.md 已说明;播放证据改为 + 固定样本的真实解码像素,保留已知尺寸限制,未改媒体实现。 + +最终源码/夹具都无生产行为变动。一次完整 CI 577 项(534+11+32)、254 个生产 TS 通过, +最终新增的浏览器观察经定向 lint 和三引擎验证。所有失败报告/trace 均复制到独立 cache 目录, +冻结 JSON 保存摘要、输入和关键状态;cache 丢失时应重跑,不能称旧 trace 仍存在。 + +## 后续修复与交接 + +- AUDIO-LIFE-01 已由旧版受控/实际媒体复现:保留的 update 可复活 src;src='' 触发新媒体错误。 + 03 应使用关闭守卫、插件自身订阅清理和无错误的媒体释放;保留同一公开 audio 及同步 update。 +- AUDIO-SYNC-01 部分已复现:主视频直接 pause 或播放结束,外部音频仍播放;03 修复原生事件同步。 + 负偏移起点/时长边界、真实缓冲和快速切源仍须在 03/05 接续,不能以本次通过关闭全部条目。 +- AUDIO-TYPE-01/DEMO-01 继续由 04/06 处理。归档分发、Monaco/8082 与设备验收尚未完成。 + +浏览器测试均共用端口 8084 和输出目录;不要同时执行多个 suite。开始下一次前复制报告 +和结果目录(包含 trace),并记录对应测试输入。Node CI 可独立并行执行。 diff --git a/refactor/baselines/audio-validation.json b/refactor/baselines/audio-validation.json new file mode 100644 index 000000000..dc92a4a03 --- /dev/null +++ b/refactor/baselines/audio-validation.json @@ -0,0 +1,7871 @@ +{ + "schemaVersion": 1, + "task": "PKG-AUDIO-02", + "capturedAt": "2026-09-11T18:08:30.994Z", + "sourceCommit": "8c0a2feed303a692fc9b37a65c116644f204429a", + "sourceHashesLF": { + "test/helpers/audio-track.js": "712ae0712e73f05843a7fac77631b31cb6fba5709b4ec195a4777c3edc21c971", + "test/audio-track.test.js": "ed54d64043e245ececf4c727512f5e33cc2268929d9b578da9b1069fdcda62a7", + "test/browser/audio-track.spec.js": "1738514af977ce4905342835a542bec3f58f49b548ff52861710bc9c81b866e7", + "test/browser/server.mjs": "4cc07efc3d5b84aa16ce691caf082b737bc704286716b321cc77a5927c77980c", + "test/browser/media/audio-tone.json": "3c87ff43501c48b984c42d6f161085f11a81099f0a38f7505d3ef3464accc330", + "packages/artplayer-plugin-audio-track/src/index.js": "470237ebd62e8fb8537e809db03fd02871844d41c03d422a22956bd2756ac28e" + }, + "media": { + "schemaVersion": 1, + "file": "audio-tone.m4a", + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436, + "command": "ffmpeg -hide_banner -loglevel error -f lavfi -i sine=frequency=440:sample_rate=48000:duration=16 -ac 1 -c:a aac -b:a 64k -map_metadata -1 -movflags +faststart test/browser/media/audio-tone.m4a", + "ffmpeg": "ffmpeg version 2025-11-12-git-6cdd2cbe32-full_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developers", + "probe": { + "programs": [], + "stream_groups": [], + "streams": [ + { + "codec_name": "aac", + "codec_type": "audio", + "sample_rate": "48000", + "channels": 1 + } + ], + "format": { + "duration": "16.000000" + } + } + }, + "node": { + "file": "refactor/.cache/audio02-node.log", + "sha256": "af97002191be56cf33a2ec0756879645487f94f86c3f74de29e373a1a5c44320", + "passed": 38, + "failed": 0, + "scope": "Source plus published main/legacy/module; controlled Audio intent, not decoding" + }, + "ci": { + "file": "refactor/.cache/audio02-ci.log", + "sha256": "516f07c5a0834c0642be3e0d632c5736e8e3dcc4fd453524f3295c22f28880e5", + "groups": [ + 534, + 11, + 32 + ], + "productionTS": 254, + "result": "passed", + "note": "Final browser-only additions subsequently passed targeted lint and browser execution; no production sources changed." + }, + "sharedInputs": { + "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881": { + "kind": "artplayer-browser-test", + "resources": { + "/candidate/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "32f3dc22e296dcc569dc1227f0b0cad92bd0dd7e74d747e19759ac5997443e92", + "bytes": 376744 + }, + "/compiled/artplayer.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "32f3dc22e296dcc569dc1227f0b0cad92bd0dd7e74d747e19759ac5997443e92", + "bytes": 376744, + "aliasOf": "/candidate/artplayer.js" + }, + "/uncompiled/artplayer/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer\\src\\index.ts" + }, + "sha256": "32f3dc22e296dcc569dc1227f0b0cad92bd0dd7e74d747e19759ac5997443e92", + "bytes": 376744, + "aliasOf": "/candidate/artplayer.js" + }, + "/candidate/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "3e8d0b7e7a90b5dbadf4cb108fd770d294f8a8a92ea089c41d0766c98bbc8230", + "bytes": 8433 + }, + "/compiled/artplayer-plugin-chapter.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "3e8d0b7e7a90b5dbadf4cb108fd770d294f8a8a92ea089c41d0766c98bbc8230", + "bytes": 8433, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/uncompiled/artplayer-plugin-chapter/index.js": { + "source": { + "kind": "workspace-build", + "entry": "packages\\artplayer-plugin-chapter\\src\\index.ts" + }, + "sha256": "3e8d0b7e7a90b5dbadf4cb108fd770d294f8a8a92ea089c41d0766c98bbc8230", + "bytes": 8433, + "aliasOf": "/candidate/artplayer-plugin-chapter.js" + }, + "/published/artplayer.js": { + "source": { + "kind": "npm-release", + "version": "5.4.0", + "integrity": "sha512-2B+plbx8N2yNsjK4nJU3+EOG8TULm1LRZk/QPkWRAMEX2Ee/MSnZG/WJYz8kcoZxZuLKcQ3uXifqLuPxZOH29A==", + "member": "package/dist/artplayer.js" + }, + "sha256": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f", + "bytes": 134037 + }, + "/published/artplayer-plugin-chapter.js": { + "source": { + "kind": "npm-release", + "version": "1.1.0", + "integrity": "sha512-ji66Lr2K2S+OjFMuMby3yq+pefWlOC51Sbpop/DIr2N6w3F0smrF+YZbshN1Dy8/Tx1TYpT7N6WkkZWy5Jix1w==", + "member": "package/dist/artplayer-plugin-chapter.js" + }, + "sha256": "c2aaee11bf1db765433b01d9f8dd3978e41fa4d39655db00ebd03fc0be3e35e0", + "bytes": 4973 + }, + "/test/pattern.mp4": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.mp4" + }, + "sha256": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233", + "bytes": 251538 + }, + "/test/pattern.webm": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/pattern.webm" + }, + "sha256": "9d3c2b3dec9581a599de2d6732992ef7846790e0d1368e6e131bd339b39e984f", + "bytes": 162073 + }, + "/test/audio-tone.m4a": { + "source": { + "kind": "generated-media", + "file": "test/browser/media/audio-tone.m4a" + }, + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436 + }, + "/test/declaration-cues.vtt": { + "source": { + "kind": "test-subtitles", + "file": "test/browser/media/declaration-cues.vtt" + }, + "sha256": "5d149d4e641ce41cbb83376835c03daf1fb89f3b9f568fa59e064d51e2b57704", + "bytes": 54 + }, + "/test/thumbnail-grid.svg": { + "source": { + "kind": "test-thumbnail-grid", + "file": "test/browser/media/thumbnail-grid.svg" + }, + "sha256": "bb3f1ec9895d37def77ca4b192d3cd73577a2668558cc99de1588f511d65d3e6", + "bytes": 14969 + }, + "/test/legacy-safe-area.js": { + "source": { + "kind": "frozen-own-source", + "file": "test/helpers/legacy-safe-area.js", + "commit": "ccf77c4e" + }, + "sha256": "ce0368618ef6363b78271b8bcc7973abd0478e797cc464ddd912929e6dfa501a", + "bytes": 795 + }, + "/assets/sample/video.mp4": { + "source": { + "kind": "docs-media", + "file": "docs/assets/sample/video.mp4" + }, + "sha256": "30a2de667ba267b6bc605edcee1c4bd728c048ed76f500ea0e73d1f1a6f8f980", + "bytes": 5818706 + }, + "/test/performance.js": { + "source": { + "kind": "adapted-baseline-fixture", + "file": "refactor/fixtures/performance.js" + }, + "sha256": "2318f39bdb5f3a3348d755cb4335907ae4adc944be3a435839c1bba201e81500", + "bytes": 8994 + } + } + }, + "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d": { + "release": { + "name": "artplayer-plugin-audio-track", + "version": "1.1.0", + "metadataUrl": "https://registry.npmjs.org/artplayer-plugin-audio-track/1.1.0", + "tarball": "https://registry.npmjs.org/artplayer-plugin-audio-track/-/artplayer-plugin-audio-track-1.1.0.tgz", + "integrity": "sha512-pvvHvTSqC2+sBelwYyjAv2CVmaQgG9KpX+i96t/e8oyZRX/JuepC9iSVIp7GzB3AtliFzhVamksT+8lXvD3RCg==", + "sha256": "7e84f6a2f4bfada428a77ef04b749bf3db53e0149fa1afe7bf5749d925e801ff", + "archiveBytes": 2205, + "registryGitHead": "daf133b22630b4a0eecfa3336bbddab0e9119d96", + "files": { + "package/README.md": "9a03352433ae90cb9d3198e17571c9bb598334b84a77a3a1df2c4b000ce8347d", + "package/dist/artplayer-plugin-audio-track.js": "473f39f1d750f0722cca7e857c12c3c978ebe3c3b2352e325f1248318e508683", + "package/dist/artplayer-plugin-audio-track.legacy.js": "d8dc74bce76112d7430c98e3165605e32fde5d3c603be4b496eac58f574576cb", + "package/dist/artplayer-plugin-audio-track.mjs": "4ac599bc5a1a6ecb0cb1942d4269528bfb2cd9d047f988de61fe671a77ad14cd", + "package/package.json": "c466ae55c40e8f6bdd97bec20fcf916c8c4f44eef3e47694638be005eb445df7", + "package/types/artplayer-plugin-audio-track.d.ts": "27bc0dfedacb7e0188cb668ac8708874a86b00d489f1636037c2465d3344437e" + }, + "manifest": { + "name": "artplayer-plugin-audio-track", + "version": "1.1.0", + "description": "audio-track plugin for ArtPlayer", + "author": "Harvey Zhao ", + "license": "MIT", + "homepage": "https://artplayer.org", + "repository": { + "type": "git", + "url": "git+https://github.com/zhw2590582/ArtPlayer.git" + }, + "bugs": { + "url": "https://github.com/zhw2590582/ArtPlayer/issues" + }, + "keywords": [ + "html5", + "video", + "player" + ], + "exports": { + ".": { + "types": "./types/artplayer-plugin-audio-track.d.ts", + "import": "./dist/artplayer-plugin-audio-track.mjs", + "require": "./dist/artplayer-plugin-audio-track.js" + }, + "./legacy": { + "types": "./types/artplayer-plugin-audio-track.d.ts", + "import": "./dist/artplayer-plugin-audio-track.legacy.js", + "require": "./dist/artplayer-plugin-audio-track.legacy.js" + } + }, + "main": "dist/artplayer-plugin-audio-track.js", + "module": "./dist/artplayer-plugin-audio-track.mjs", + "types": "types/artplayer-plugin-audio-track.d.ts", + "legacy": "dist/artplayer-plugin-audio-track.legacy.js", + "browserslist": "last 1 Chrome version" + } + }, + "sourceSHA256": "6387f66ef15194b78336ee6256b744862e7e27a41aaab96275dcaea2f8967aa8", + "audio": { + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436, + "format": "AAC mono 48000 Hz, 16 seconds, 440 Hz tone in MP4" + }, + "wav": { + "sha256": "3150fc69aa2b94a4b556e2e6d9d67fb52c2926cd144fdd8694a7f8ddfd2f15ff", + "bytes": 512044, + "format": "PCM16LE mono 16000 Hz, 16 seconds, integer square wave 200 Hz" + }, + "scope": "Source browser baseline; no physical device or installed package acceptance" + } + }, + "browserRuns": [ + { + "file": "refactor/.cache/audio02-browser-first.json", + "sha256": "e8e4bd04a8a0fa68a8c9198391a8df1abc70370043559485baf3b428aee1750f", + "interpretation": "24 failures: wrong seek API, empty-src cleanup and Windows WebKit WAV", + "stats": { + "startTime": "2026-09-11T17:53:18.221Z", + "duration": 79655.926, + "expected": 0, + "skipped": 0, + "unexpected": 24, + "flaky": 0 + }, + "cases": [ + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.324114\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.925886\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.324114, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0.001279, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.324114, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0.000315, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.322912\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.927088\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.322912, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0.000211, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.322912, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0.000194, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.327913\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.9220869999999999\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.327913, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0.000297, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.327913, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0.002347, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.329371\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.920629\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.329371, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0.000326, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.329371, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0.002364, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.371519\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.878481\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.371519, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.371519, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.416882\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.833118\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.416882, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.416882, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.377871\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.872129\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.377871, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.377871, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0.374877\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 1.8751229999999999\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0.374877, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + }, + { + "event": "pause", + "time": 0.374877, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBe(expected) // Object.is equality\n\nExpected: \"\"\nReceived: \"http://127.0.0.1:8084/audio-fixture/recovered.wav\"\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.wav" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeGreaterThanOrEqual(expected)\n\nExpected: >= 2\nReceived: 0\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 2, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.wav" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.wav" + } + ], + "warnings": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/audio02-chromium.json", + "sha256": "6b59598124ac0bb115d679b8a52f08393ebdd6149696e0e47686b1efe03ebf5d", + "interpretation": "6 passed / 4 failed: AAC route without Range did not support seek", + "stats": { + "startTime": "2026-09-11T17:59:11.777Z", + "duration": 23031.971999999998, + "expected": 6, + "skipped": 0, + "unexpected": 4, + "flaky": 0 + }, + "cases": [ + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": {} + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "playing", + "time": 0.000205, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 2.25\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a", + "attribute": "/audio-fixture/first.m4a", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "playing", + "time": 0.000188, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "pause", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "seeked", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "playing", + "time": 0.000283, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 2.25\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a", + "attribute": "/audio-fixture/first.m4a", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "playing", + "time": 0.000233, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "pause", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "seeked", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "playing", + "time": 0.000285, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 2.25\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a", + "attribute": "/audio-fixture/first.m4a", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "playing", + "time": 0.001725, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "pause", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "seeked", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "playing", + "time": 0.000277, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toBeCloseTo(expected, precision)\n\nExpected: 2.25\nReceived: 0\n\nExpected precision: 1\nExpected difference: < 0.05\nReceived difference: 2.25\n\nCall Log:\n- Timeout 7000ms exceeded while waiting on the predicate", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a", + "attribute": "/audio-fixture/first.m4a", + "time": 0, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 2, + "paused": true, + "readyState": 4, + "networkState": 1, + "rate": 1 + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "playing", + "time": 0.000241, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "pause", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + }, + { + "event": "seeked", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/first.m4a" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1 + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1 + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "playing", + "time": 0.000299, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/recovered.m4a" + } + ], + "warnings": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/audio02-chromium-range.json", + "sha256": "68952b63475761db9d4a56519f4b02947a22c185182f817ee6edad243c089a91", + "interpretation": "10 passed using the existing Range server", + "stats": { + "startTime": "2026-09-11T18:00:57.027Z", + "duration": 7574.789, + "expected": 10, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": {} + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000146, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.00019, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.258203, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.258203, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.258761, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.25878, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000154, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.002997, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.270305, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.270305, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.270382, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.270403, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.00022, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000234, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.268982, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.268982, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.270091, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.270107, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000231, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.002769, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.270209, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.270209, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.270415, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.270436, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.002267, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/audio02-browser-range.json", + "sha256": "143c3b6d1c255e3c24c645b3b09ac64f7643509f83c5d039ec8d37a780d32d2f", + "interpretation": "26 passed / 4 failed: documented Windows WebKit layout-sized height", + "stats": { + "startTime": "2026-09-11T18:01:33.855Z", + "duration": 26463.798, + "expected": 26, + "skipped": 0, + "unexpected": 4, + "flaky": 0 + }, + "cases": [ + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": {} + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.001914, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000254, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.270124, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.270124, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.270213, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.270228, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000277, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.00338, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.269683, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.269683, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.269787, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.269805, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000298, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000297, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.269473, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.269473, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.269572, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.269593, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000452, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.002871, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.269041, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.269041, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.269145, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.269157, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000354, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": {} + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.499999, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.499999, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": {} + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.02, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toEqual(expected) // deep equality\n\n- Expected - 1\n+ Received + 1\n\n Object {\n \"duration\": 16,\n- \"height\": 180,\n+ \"height\": 360,\n }", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "/test/audio-tone.m4a?source=first", + "time": 0.6807906, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 16 + ] + ] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 0.7127177, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 8 + ] + ] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toEqual(expected) // deep equality\n\n- Expected - 1\n+ Received + 1\n\n Object {\n \"duration\": 16,\n- \"height\": 180,\n+ \"height\": 360,\n }", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "/test/audio-tone.m4a?source=first", + "time": 0.7197489, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 16 + ] + ] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 0.7327382, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 8 + ] + ] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toEqual(expected) // deep equality\n\n- Expected - 1\n+ Received + 1\n\n Object {\n \"duration\": 16,\n- \"height\": 180,\n+ \"height\": 360,\n }", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "/test/audio-tone.m4a?source=first", + "time": 0.6183532, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 16 + ] + ] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 0.6504937, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 8 + ] + ] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "failed", + "retry": 0, + "error": "Error: expect(received).toEqual(expected) // deep equality\n\n- Expected - 1\n+ Received + 1\n\n Object {\n \"duration\": 16,\n- \"height\": 180,\n+ \"height\": 360,\n }", + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "/test/audio-tone.m4a?source=first", + "time": 0.6066032, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 16 + ] + ] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": "/test/pattern.mp4", + "time": 0.6337551, + "paused": false, + "readyState": 4, + "networkState": 2, + "rate": 1, + "seekable": [ + [ + 0, + 8 + ] + ] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + } + } + } + ] + }, + { + "file": "refactor/.cache/audio02-browser-confirm.json", + "sha256": "d9a27059fc1cbbc64de7c4b7c9a43803982428a099a75b2e7bb9076a4e6b4940", + "interpretation": "36 passed: final AAC matrix including published defects and native WAV diagnostic", + "stats": { + "startTime": "2026-09-11T18:03:36.467Z", + "duration": 31052.743, + "expected": 36, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "cases": [ + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "native-wav-capability": { + "canPlay": "maybe", + "readyState": 4, + "error": null, + "playerCreated": false + }, + "audio-state": {}, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.00024, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "published core + published audio: native pause and end leave external audio playing", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.124199 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000341, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 255, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000248, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.268837, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.268837, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.268903, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.268916, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000396, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [ + "Failed to load resource: the server responded with a status of 503 (Service Unavailable)" + ], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 255, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000175, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.267919, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.267919, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.267999, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.268015, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000352, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [ + "Failed to load resource: the server responded with a status of 503 (Service Unavailable)" + ], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "candidate core + published audio: native pause and end leave external audio playing", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.121094 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000279, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 7.800231, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 255, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.00031, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.268604, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.268604, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.268695, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.268709, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000282, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [ + "Failed to load resource: the server responded with a status of 503 (Service Unavailable)" + ], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 255, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.000281, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 2.268601, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 2.268601, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.269358, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.269371, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "chromium", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.000396, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "153.0.8010.12", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/153.0.8010.12 Safari/537.36", + "media": null + }, + "errors": [], + "consoleErrors": [ + "Failed to load resource: the server responded with a status of 503 (Service Unavailable)" + ], + "failedRequests": [ + { + "url": "http://127.0.0.1:8084/test/pattern.mp4", + "resourceType": "media", + "failure": { + "errorText": "net::ERR_ABORTED" + } + } + ] + } + } + }, + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "native-wav-capability": { + "canPlay": "maybe", + "readyState": 4, + "error": null, + "playerCreated": false + }, + "audio-state": {}, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: native pause and end leave external audio playing", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.043114 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 241, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 241, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: native pause and end leave external audio playing", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.087428 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 241, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 255, + 241, + 2, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.541666, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "firefox", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "155.0", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:155.0) Gecko/20100101 Firefox/155.0", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "native WAV diagnostic isolates sample decoding from ArtPlayer and plugin", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "native-wav-capability": { + "canPlay": "probably", + "readyState": 0, + "error": 4, + "playerCreated": false + }, + "audio-state": {}, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published AUDIO-LIFE-01: empty src cleanup produces a native media error", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: native pause and end leave external audio playing", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.2911034 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.81, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 235, + 236, + 12, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.03, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.6730056, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 2.6730056, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 235, + 236, + 12, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.6467672, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "published core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0.0009792, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=published", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: native pause and end leave external audio playing", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "published-native-pause-end": { + "videoEnded": true, + "videoPaused": true, + "audioPaused": false, + "audioTime": 8.2229369 + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.02, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 7.8, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 235, + 236, + 12, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.26, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.6560003, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + published audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + source audio: decoded play, offset seek, rate, source and cleanup", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "decoded-frame-pixel": [ + 235, + 236, + 12, + 255 + ], + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "pause", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "seeked", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "playing", + "time": 2.25, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=first" + }, + { + "event": "loadedmetadata", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "playing", + "time": 0.01, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "seeked", + "time": 2.6667932, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=second" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + }, + { + "title": "candidate core + source audio: real load error can recover with a new source", + "engine": "webkit", + "status": "passed", + "retry": 0, + "attachments": { + "audio-inputs": { + "sharedInput": "7888fc414bee1c270ad321ef3bc37f7cb64d0c75a185a4808850e3bcac7d150d" + }, + "audio-state": { + "audio": { + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered", + "attribute": "", + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 3, + "error": 4, + "rate": 1, + "seekable": [] + }, + "video": { + "src": "http://127.0.0.1:8084/test/pattern.mp4", + "attribute": null, + "time": 0, + "paused": true, + "readyState": 0, + "networkState": 0, + "rate": 1, + "seekable": [] + }, + "events": [ + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/audio-fixture/broken.m4a" + }, + { + "event": "loadedmetadata", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "playing", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "emptied", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + }, + { + "event": "error", + "time": 0, + "src": "http://127.0.0.1:8084/test/audio-tone.m4a?source=recovered" + } + ], + "warnings": [] + }, + "browser-evidence": { + "browser": "26.6", + "platform": "win32", + "manifest": { + "sharedInput": "27258261e9ce712f0e40c6c6b61f26571d2e91ceb961928c08c664edef2ab881" + }, + "state": { + "url": "http://127.0.0.1:8084/test/player.html?core=candidate", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.6 Safari/605.1.15", + "media": null + }, + "errors": [], + "consoleErrors": [], + "failedRequests": [] + } + } + } + ] + } + ], + "limitations": [ + "Source builds, not isolated installed artifacts", + "AAC and local video are not all codec coverage", + "Native WAV records Windows WebKit unsupported result, not playback certification", + "Published defect test passes mean reproduced, not fixed", + "No physical iOS/Android/Safari, acoustic output capture or autoplay policy certification" + ] +} diff --git a/refactor/changes/2026-09-12-PKG-AUDIO-02-tests.md b/refactor/changes/2026-09-12-PKG-AUDIO-02-tests.md new file mode 100644 index 000000000..2a547a324 --- /dev/null +++ b/refactor/changes/2026-09-12-PKG-AUDIO-02-tests.md @@ -0,0 +1,43 @@ +# PKG-AUDIO-02:外部音频行为基线 + +状态:本步测试基线验收完成;起点 8c0a2fee。遵循已冻结的 Audio Track 1.1.0 契约。 +范围是源码及真实发布三格式的可控行为、错误与生命周期测试,以及真实浏览器的 +外部音频/主视频播放、seek、切源和清理。受控 Audio 不被描述为真实解码证据。 +公开行为不在本步修改;复现的历史问题交由 03 修复、04 类型迁移。 + +## 交付与验证 + +新增 test/audio-track.test.js 和窄范围受控 Audio helper,源码及发布三格式共 38 项通过。 +公开 audio、工厂延迟安装、默认阈值、偏移正负、配置更新、事件、Promise 拒绝及清理均覆盖。 +Node 测试加入现有 test:unit 脚本,不新增依赖或 lock 改动。 + +新增 audio-track.spec.js 和自行生成的 AAC 媒体/来源 manifest,服务器复用 Range 处理。 +三引擎最终 36 项通过(其中 9 项历史缺陷复现、3 项原生能力诊断),没有重试/跳过。 +音频与视频时钟、真实解码像素、偏移 seek、音量倍率、换音源/错误恢复、清理状态均验证。 +577 项完整 CI、254 生产 TS 通过。最终浏览器补充又通过定向 lint 与三引擎执行。 +计划/风险生成校验和 Git diff 检查通过:216 项任务、126 项风险,未豁免未解决项。 + +原始失败及下一步见 [测试说明](../audio-validation.md),所有输入/关键状态/报告哈希冻结在 +[执行证据](../baselines/audio-validation.json)。首轮 fixture 调用错误、Range 不完整、 +WebKit 尺寸假设分别修正,没有增加超时或删掉真实播放/seek 断言。 +最初定向 lint 有换行/多语句格式错误,按现有规范修正;受控测试多宿主改为单次全局 Audio +安装,避免多组恢复钩子的顺序污染,最终 CI 通过。 + +## 兼容、缺陷与范围 + +生产源码/声明/构建产物没有变更,没有新增 API、DOM/CSS 或消费者依赖。 +AUDIO-LIFE-01:发布版保留 update 可在 destroy 后写 src,且空 src 清理导致浏览器 error=4。 +AUDIO-SYNC-01:真实旧核心及候选核心中,原生暂停/自然结束后外部音频仍继续播放。 +两项保持 open,由 03 修复;本步仅把证据等级更新为已复现。 + +负偏移起点、超时长、真实缓冲、快速切源、设备策略仍需 03/05 接续。 +WAV 在 Windows WebKit 的原生 Audio 也失败,AAC 通过不替代 WAV 或真实 Safari 认证。 +未测扬声器声音、物理设备和隔离安装包;不以本次基线关闭包发布门槛。 +实际生产模块地图随 03 源码变化交付,本步提供可重跑维护入口。 + +## 提交与回退 + +独立完成提交主题:`test(audio): [PKG-AUDIO-02] cover released behavior and real media`。 +回退本提交可移除新增测试/fixture/脚本接入和文档,生产播放器不受影响。 +下一步 03 开始同步与生命周期源码拆分/修复,04 接续严格 TS/公开类型。 +未 push/tag/publish/merge,全项目目标保持。 diff --git a/refactor/plan.md b/refactor/plan.md index 687287541..6e7ad17de 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -4,7 +4,7 @@ 基线:`40fcda6a37d0049d42e49c1e64e70d4fd9ba5f7f`。总任务 216 项,范围 22 个包及工作区/示例。 -状态:todo 149 / doing 1 / blocked 0 / done 66 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 +状态:todo 148 / doing 1 / blocked 0 / done 67 / deferred 0。风险 L/M/H 表示兼容风险,不表示工期。 前置依赖是启动条件;验收是完成条件。任务可以继续拆分,但不能复用或悄悄删除旧 ID。 @@ -156,7 +156,7 @@ | ID | 范围 / 步骤 | 前置依赖 | 交付物 | 验收条件 | 风险 | 状态 | | --- | --- | --- | --- | --- | --- | --- | | PKG-AUDIO-01 | artplayer-plugin-audio-track
核对包契约与历史用法 | BASE-05 | url/offset/sync、audio 实例暴露、update 与音量语义 | 源码/声明/README/demo/发布包差异已登记;公开形状和版本范围冻结 | H | done | -| PKG-AUDIO-02 | artplayer-plugin-audio-track
建立特有行为与错误测试 | PKG-AUDIO-01, ENG-03, ENG-05 | 偏移、倍率、seek、waiting/playing、加载错误和 autoplay 拒绝 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | todo | +| PKG-AUDIO-02 | artplayer-plugin-audio-track
建立特有行为与错误测试 | PKG-AUDIO-01, ENG-03, ENG-05 | 偏移、倍率、seek、waiting/playing、加载错误和 autoplay 拒绝 | 旧版本行为可重跑,成功/失败/切源/销毁有必要断言 | H | done | | PKG-AUDIO-03 | artplayer-plugin-audio-track
整理内部职责与资源 | PKG-AUDIO-02, CORE-10 | 外部 audio 的同步策略、监听与源更新生命周期 | 结构变化和缺陷修复分开记录;原 API/事件/资源生命周期通过 | H | todo | | PKG-AUDIO-04 | artplayer-plugin-audio-track
迁移自有源码和公开类型 | PKG-AUDIO-03, ENG-04, ENG-06, CORE-07 | Option/Result/audio、update 输入和事件类型 | 严格类型检查、旧消费样例通过;声明路径/导出和同步异步兼容 | H | todo | | PKG-AUDIO-05 | artplayer-plugin-audio-track
验证新旧核心和组合 | PKG-AUDIO-04, CORE-22 | 主视频切源和缓冲恢复,多实例独立音频、旧核心 | 最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成 | H | todo | @@ -467,6 +467,7 @@ - PKG-CHAPTER-03: [记录](changes/2026-09-10-PKG-CHAPTER-03-typescript-modules.md) [记录](baselines/chapter-migration-validation.json) - PKG-CHAPTER-04: [记录](changes/2026-09-10-PKG-CHAPTER-04-public-types.md) [记录](baselines/chapter-types-validation.json) - PKG-AUDIO-01: [记录](changes/2026-09-12-PKG-AUDIO-01-contract.md) [记录](baselines/audio-track-contract.md) [记录](baselines/audio-track-release.json) +- PKG-AUDIO-02: [记录](changes/2026-09-12-PKG-AUDIO-02-tests.md) [记录](audio-validation.md) [记录](baselines/audio-validation.json) - PKG-HLS-01: [记录](baselines/hls-control-contract.md) [记录](baselines/hls-control-release.json) [记录](changes/2026-09-11-PKG-HLS-01-contract.md) - PKG-HLS-02: [记录](hls-validation.md) [记录](baselines/hls-sdk.json) [记录](baselines/hls-validation.json) [记录](changes/2026-09-11-PKG-HLS-02-tests.md) - PKG-HLS-03: [记录](changes/2026-09-12-PKG-HLS-03-modules.md) [记录](baselines/hls-modules-validation.json) [记录](hls-validation.md) diff --git a/refactor/progress.md b/refactor/progress.md index ae0a5a700..ea552bb04 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,18 @@ # 进度与证据 +## 最新完成:PKG-AUDIO-02 行为与真实媒体基线 + +38 项 Node 契约覆盖源码和发布三格式,完整 CI 577 项、254 个生产 TS 通过。 +三引擎最终 36 项通过、零失败/重试/跳过;其中 9 项为旧版缺陷复现、3 项为原生 WAV +能力诊断,不能把这些数量全部作为无缺陷候选验收。真实 AAC/视频播放、偏移 seek、 +音量倍率、音频切源/503 恢复已验证。原始夹具失败与归因/trace 均保留。 + +旧插件销毁后 update 可复活、src='' 新生媒体错误、原生视频暂停/结束未停外部音频 +已有证据;AUDIO-LIFE-01/SYNC-01 仍 open,03 接续源码拆分修复。 +当前 216 项、67 done、1 doing、148 todo;HLS 仍保持原发布门槛。 +Audio-01 已提交 8c0a2fee,Audio-02 独立本地提交后核实,再进入 03。 +详见 [测试说明](audio-validation.md) 和 [记录](changes/2026-09-12-PKG-AUDIO-02-tests.md)。 + ## 最新完成:PKG-AUDIO-01 外部音轨发布契约 冻结 npm audio-track 1.1.0 六文件及完整性,manifest/README/声明和起点一致, diff --git a/refactor/risk-table.md b/refactor/risk-table.md index d8709ea94..3bf771a48 100644 --- a/refactor/risk-table.md +++ b/refactor/risk-table.md @@ -126,7 +126,7 @@ | HLS-ENV-01 | open / 已复现 | Windows WebKit 缺失 MSE,HLS 播放矩阵尚缺 Safari 证据 | PKG-HLS-05, REL-09, REVIEW-02 | | HLS-CRASH-01 | open / 已复现 | Firefox Hls 1.5.17 worker 销毁可在原生 video 与候选核心复现崩溃 | PKG-HLS-SDK-01, PKG-HLS-05, REVIEW-02 | | HLS-PLAYBACK-01 | open / 已复现 | Firefox 旧核心与 Hls 1.7.2 切组后视频档位未完成切换 | PKG-HLS-SDK-01, PKG-HLS-05, REVIEW-02 | -| AUDIO-LIFE-01 | open / 源码/产物事实 | Audio Track 销毁后 update 与媒体/订阅缺少终止守卫 | PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-05 | -| AUDIO-SYNC-01 | open / 待取证 | Audio Track 偏移边界和切源/缓冲恢复尚缺真实时序证据 | PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-05 | +| AUDIO-LIFE-01 | open / 已复现 | Audio Track 销毁后 update 与媒体/订阅缺少终止守卫 | PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-05 | +| AUDIO-SYNC-01 | open / 已复现 | Audio Track 未同步原生暂停/结束,偏移边界与切源/缓冲仍待完整验证 | PKG-AUDIO-02, PKG-AUDIO-03, PKG-AUDIO-05 | | AUDIO-TYPE-01 | open / 源码/产物事实 | Audio Track update 部分配置与公开/编辑器声明不一致 | PKG-AUDIO-04 | | AUDIO-DEMO-01 | open / 源码/产物事实 | Audio Track README 示例链接名称不匹配且缺维护说明 | PKG-AUDIO-06 | diff --git a/refactor/risks.json b/refactor/risks.json index 920c3257b..70da2f8d3 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -2647,7 +2647,7 @@ { "id": "AUDIO-LIFE-01", "title": "Audio Track 销毁后 update 与媒体/订阅缺少终止守卫", - "confirmation": "source-observed", + "confirmation": "reproduced", "status": "open", "owners": [ "PKG-AUDIO-02", @@ -2656,15 +2656,18 @@ ], "evidence": [ "refactor/baselines/audio-track-contract.md", - "refactor/baselines/audio-track-release.json" + "refactor/baselines/audio-track-release.json", + "test/audio-track.test.js", + "test/browser/audio-track.spec.js", + "refactor/baselines/audio-validation.json" ], "compatibleResolution": "保留公开 audio 和同步 update,封闭销毁后的资源写入并管理插件订阅,验证待决播放拒绝。", "closureCriteria": "受控复现和新旧核心真实媒体切源/销毁验证通过,不以源码观察代替泄漏证据。" }, { "id": "AUDIO-SYNC-01", - "title": "Audio Track 偏移边界和切源/缓冲恢复尚缺真实时序证据", - "confirmation": "unverified", + "title": "Audio Track 未同步原生暂停/结束,偏移边界与切源/缓冲仍待完整验证", + "confirmation": "reproduced", "status": "open", "owners": [ "PKG-AUDIO-02", @@ -2673,7 +2676,10 @@ ], "evidence": [ "refactor/baselines/audio-track-contract.md", - "refactor/baselines/audio-track-release.json" + "refactor/baselines/audio-track-release.json", + "test/audio-track.test.js", + "test/browser/audio-track.spec.js", + "refactor/baselines/audio-validation.json" ], "compatibleResolution": "固定严格阈值、偏移正负、倍率和音量语义;实测负目标/超时长及连续切源,按证据修复。", "closureCriteria": "正常/边界/失败/缓冲恢复有媒体与受控断言,实际支持环境缺口明确处理。" diff --git a/refactor/tasks.json b/refactor/tasks.json index c39901f37..b55ce46f2 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -1490,11 +1490,15 @@ "ENG-03", "ENG-05" ], - "status": "todo", + "status": "done", "risk": "H", "deliverable": "偏移、倍率、seek、waiting/playing、加载错误和 autoplay 拒绝", "acceptance": "旧版本行为可重跑,成功/失败/切源/销毁有必要断言", - "evidence": [] + "evidence": [ + "changes/2026-09-12-PKG-AUDIO-02-tests.md", + "audio-validation.md", + "baselines/audio-validation.json" + ] }, { "id": "PKG-AUDIO-03", diff --git a/test/README.md b/test/README.md index e138c5aea..3cbebf059 100644 --- a/test/README.md +++ b/test/README.md @@ -40,3 +40,8 @@ Blob URL contents and cleanup when a controlled click fails. See [browser/README.md](browser/README.md) for `yarn test:browser`, browser installation, published/current combinations, media fixtures, candidate mapping and failure reports. These tests are separate from the fast Node suite and run in the Browser playback smoke CI job. + +`test/audio-track.test.js` compares source and published Audio Track 1.1.0 in all three +formats with a controlled Audio object: timing intent, offsets, source updates, rejection, +volume/rate, independent instances and cleanup. Published-only tests retain defect evidence. +See [audio validation](../refactor/audio-validation.md) for actual media tests and limitations. diff --git a/test/audio-track.test.js b/test/audio-track.test.js new file mode 100644 index 000000000..92bf5ea87 --- /dev/null +++ b/test/audio-track.test.js @@ -0,0 +1,167 @@ +import assert from 'node:assert/strict' +// eslint-disable-next-line test/no-import-node-test -- Controlled media contracts use Node's runner. +import { test } from 'node:test' +import { audioHost, audioImplementations, createAudioArt } from './helpers/audio-track.js' + +const implementations = await audioImplementations() +for (const { name, factory } of implementations) { + test(`${name}: synchronous lazy installation, exposed audio and initial media properties`, (t) => { + const { art, instances } = audioHost(t) + const option = { url: 'first.aac' } + const attach = factory(option) + assert.equal(instances.length, 0) + option.url = 'before-install.aac' + const plugin = attach(art) + assert.equal(plugin.name, 'artplayerPluginAudioTrack') + assert.deepEqual(Object.keys(plugin).sort(), ['audio', 'name', 'update']) + assert.equal(plugin.audio, instances[0]) + assert.deepEqual(plugin.audio.calls, [['preload', 'auto'], ['src', 'before-install.aac'], ['volume', 0.6], ['muted', false], ['playbackRate', 1.25]]) + assert.equal(plugin.update({}), undefined) + assert.equal(art.muted, false, 'Plugin must not mute the main video') + }) + + test(`${name}: default threshold is strict and offset applies in both directions`, (t) => { + const { art } = audioHost(t) + const { audio, update } = factory({ url: 'audio.aac' })(art) + audio.calls.length = 0 + art.currentTime = 0.3 + art.emit('seek') + assert.deepEqual(audio.calls, []) + art.currentTime = 0.31 + art.emit('seek') + assert.deepEqual(audio.calls, [['currentTime', 0.31]]) + update({ offset: 2, sync: 0 }) + art.currentTime = 4 + art.emit('seek') + assert.equal(audio.currentTime, 6) + update({ offset: -1 }) + art.emit('seek') + assert.equal(audio.currentTime, 3) + }) + + test(`${name}: play synchronizes before playback and timeupdate only follows playing video`, (t) => { + const { art } = audioHost(t) + const { audio } = factory({ url: 'audio.aac' })(art) + audio.calls.length = 0 + art.currentTime = 4 + art.emit('video:timeupdate') + assert.deepEqual(audio.calls, []) + art.emit('play') + assert.deepEqual(audio.calls, [['currentTime', 4], ['play']]) + art.playing = true + art.currentTime = 5 + art.emit('video:timeupdate') + assert.equal(audio.currentTime, 5) + art.video = null + audio.calls.length = 0 + art.emit('seek') + assert.deepEqual(audio.calls, []) + }) + + test(`${name}: waiting pauses, playing resumes conditionally, pause always stops audio`, (t) => { + const { art } = audioHost(t) + const { audio } = factory({ url: 'audio.aac' })(art) + audio.calls.length = 0 + art.emit('video:waiting').emit('video:playing') + assert.deepEqual(audio.calls, [['pause']]) + art.playing = true + art.emit('video:playing').emit('pause') + assert.deepEqual(audio.calls, [['pause'], ['play'], ['pause']]) + }) + + test(`${name}: independent volume mute and rate changes follow the host`, (t) => { + const { art } = audioHost(t) + const { audio } = factory({ url: 'audio.aac' })(art) + art.volume = 0 + art.muted = true + art.video.playbackRate = 2 + art.emit('video:volumechange').emit('video:ratechange') + assert.equal(audio.volume, 0) + assert.equal(audio.muted, true) + assert.equal(audio.playbackRate, 2) + art.video = undefined + assert.equal(factory({ url: '' })(art).audio.playbackRate, 1) + }) + + test(`${name}: same and empty URLs do not reload; changed source preserves audio identity`, (t) => { + const { art, instances } = audioHost(t) + const plugin = factory({ url: 'audio.aac' })(art) + plugin.audio.calls.length = 0 + plugin.update({ url: 'audio.aac' }) + plugin.update({ url: '' }) + assert.deepEqual(plugin.audio.calls, []) + assert.equal(plugin.update({ url: 'paused.aac' }), undefined) + assert.deepEqual(plugin.audio.calls, [['src', 'paused.aac']]) + art.playing = true + plugin.audio.calls.length = 0 + plugin.update({ url: 'playing.aac' }) + assert.deepEqual(plugin.audio.calls, [['src', 'playing.aac'], ['play']]) + assert.equal(plugin.audio, instances[0]) + assert.equal(instances.length, 1) + }) + + test(`${name}: an empty initial URL stays inert until configured`, (t) => { + const { art } = audioHost(t) + const { audio, update } = factory({ url: '' })(art) + art.currentTime = 3 + art.playing = true + audio.calls.length = 0 + art.emit('play').emit('seek').emit('video:timeupdate').emit('video:playing') + assert.deepEqual(audio.calls, []) + update({ url: 'configured.aac' }) + assert.deepEqual(audio.calls, [['src', 'configured.aac'], ['play']]) + }) + + test(`${name}: rejection at all three play sites is observed as the original warning`, async (t) => { + const { art, setPlay, warnings } = audioHost(t) + const plugin = factory({ url: 'audio.aac' })(art) + const rejection = new Error('Controlled NotAllowedError') + setPlay(() => Promise.reject(rejection)) + art.playing = true + art.emit('play') + await Promise.resolve() + art.emit('video:playing') + await Promise.resolve() + assert.equal(plugin.update({ url: 'next.aac' }), undefined) + await Promise.resolve() + assert.deepEqual(warnings, [rejection, rejection, rejection]) + }) + + test(`${name}: destroy releases the exposed media and multiple hosts stay independent`, (t) => { + const first = audioHost(t) + const second = createAudioArt() + const left = factory({ url: 'left.aac' })(first.art) + const right = factory({ url: 'right.aac' })(second.art) + assert.notEqual(left.audio, right.audio) + left.audio.calls.length = 0 + right.audio.calls.length = 0 + first.art.emit('destroy') + assert.deepEqual(left.audio.calls, [['pause'], ['src', ''], ['load']]) + assert.deepEqual(right.audio.calls, []) + second.art.currentTime = 2 + second.art.emit('seek') + assert.equal(right.audio.currentTime, 2) + }) +} + +const historical = implementations.find(item => item.name === 'published-main').factory +test('published defect AUDIO-LIFE-01: retained update reloads audio after destroy', (t) => { + const { art, listeners } = audioHost(t) + const plugin = historical({ url: 'audio.aac' })(art) + art.emit('destroy') + plugin.audio.calls.length = 0 + plugin.update({ url: 'revived.aac' }) + assert.deepEqual(plugin.audio.calls, [['src', 'revived.aac']]) + assert.equal([...listeners.values()].reduce((count, set) => count + set.size, 0), 9) +}) + +test('published observation: offset update is deferred, negative target is written without clamping', (t) => { + const { art } = audioHost(t) + const plugin = historical({ url: 'audio.aac' })(art) + plugin.audio.calls.length = 0 + plugin.update({ offset: -2 }) + assert.deepEqual(plugin.audio.calls, []) + art.currentTime = 0 + art.emit('seek') + assert.deepEqual(plugin.audio.calls, [['currentTime', -2]]) +}) diff --git a/test/browser/README.md b/test/browser/README.md index 9ca7c0a6a..770224280 100644 --- a/test/browser/README.md +++ b/test/browser/README.md @@ -1,5 +1,10 @@ # Browser regression entry +Audio Track tests use the source and frozen 1.1.0 plugin on both cores. The local AAC fixture +has a pinned hash and generation command in media/audio-tone.json and uses the existing Range +server. The suite retains published cleanup/native-pause defects as explicit observations. +See [audio validation](../../refactor/audio-validation.md) for passed scope and device limitations. + Use the pinned Node and Yarn versions, then run: ```sh diff --git a/test/browser/audio-track.spec.js b/test/browser/audio-track.spec.js new file mode 100644 index 000000000..384989862 --- /dev/null +++ b/test/browser/audio-track.spec.js @@ -0,0 +1,206 @@ +import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import fs from 'node:fs' +import process from 'node:process' +import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' +import { compilePackage } from '../helpers/load.js' +import { expect, test } from './fixtures.js' + +let publishedCode +let sourceCode +let evidence +const samples = 16000 * 16 +const tone = fs.readFileSync(new URL('./media/audio-tone.m4a', import.meta.url)) +const toneManifest = JSON.parse(fs.readFileSync(new URL('./media/audio-tone.json', import.meta.url))) +const wav = Buffer.alloc(44 + samples * 2) +wav.write('RIFF', 0) +wav.writeUInt32LE(wav.length - 8, 4) +wav.write('WAVEfmt ', 8) +wav.writeUInt32LE(16, 16) +wav.writeUInt16LE(1, 20) +wav.writeUInt16LE(1, 22) +wav.writeUInt32LE(16000, 24) +wav.writeUInt32LE(32000, 28) +wav.writeUInt16LE(2, 32) +wav.writeUInt16LE(16, 34) +wav.write('data', 36) +wav.writeUInt32LE(samples * 2, 40) +for (let index = 0; index < samples; index++) + wav.writeInt16LE(index % 80 < 40 ? 2000 : -2000, 44 + index * 2) + +test.beforeAll(async () => { + assert.equal(hash(tone), toneManifest.sha256) + assert.equal(tone.length, toneManifest.bytes) + assert(!process.env.ARTPLAYER_BROWSER_ARTIFACTS, 'Audio source tests cannot represent installed artifacts') + const { release } = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/audio-track-release.json', import.meta.url))) + const member = 'package/dist/artplayer-plugin-audio-track.js' + const bytes = readMember(await ensureArchive(release), member) + assert.equal(hash(bytes), release.files[member]) + publishedCode = bytes.toString() + sourceCode = await compilePackage(release.name, 'umd') + evidence = { release, sourceSHA256: hash(sourceCode), audio: { sha256: hash(tone), bytes: tone.length, format: 'AAC mono 48000 Hz, 16 seconds, 440 Hz tone in MP4' }, wav: { sha256: hash(wav), bytes: wav.length, format: 'PCM16LE mono 16000 Hz, 16 seconds, integer square wave 200 Hz' }, scope: 'Source browser baseline; no physical device or installed package acceptance' } +}) + +test.afterEach(async ({ page }, testInfo) => { + const state = await page.evaluate(() => { + const audio = window.audioPlugin?.audio + const video = window.art?.video + const media = element => element && ({ src: element.currentSrc, attribute: element.getAttribute('src'), time: element.currentTime, paused: element.paused, readyState: element.readyState, networkState: element.networkState, error: element.error?.code, rate: element.playbackRate, seekable: Array.from({ length: element.seekable.length }, (_, index) => [element.seekable.start(index), element.seekable.end(index)]) }) + return { audio: media(audio), video: media(video), events: window.audioEvents, warnings: window.audioWarnings } + }).catch(error => ({ error: error.message })) + await testInfo.attach('audio-state', { contentType: 'application/json', body: JSON.stringify(state) }) +}) + +async function openAudio(page, core, plugin, testInfo, url = '/test/audio-tone.m4a?source=first') { + await testInfo.attach('audio-inputs', { contentType: 'application/json', body: JSON.stringify(evidence) }) + await page.goto(`/test/player.html?core=${core}`) + await page.addScriptTag({ content: plugin === 'published' ? publishedCode : sourceCode }) + await page.evaluate((url) => { + window.audioEvents = [] + window.audioWarnings = [] + const warn = console.warn.bind(console) + console.warn = (...args) => { + window.audioWarnings.push(args.map(String)) + warn(...args) + } + window.art = new window.Artplayer({ + container: '.player', + url: '/test/pattern.mp4', + muted: true, + plugins: [window.artplayerPluginAudioTrack({ url, sync: 0.1 })], + }) + window.audioPlugin = window.art.plugins.artplayerPluginAudioTrack + for (const event of ['loadedmetadata', 'playing', 'pause', 'seeked', 'error', 'emptied']) + window.audioPlugin.audio.addEventListener(event, () => window.audioEvents.push({ event, time: window.audioPlugin.audio.currentTime, src: window.audioPlugin.audio.currentSrc })) + document.querySelector('#play').onclick = () => window.art.play() + }, url) + await expect.poll(() => page.evaluate(() => window.art.isReady)).toBe(true) + if (url) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.readyState)).toBeGreaterThanOrEqual(2) +} + +test('native WAV diagnostic isolates sample decoding from ArtPlayer and plugin', async ({ page }, testInfo) => { + await page.route('**/native-wave.wav', route => route.fulfill({ contentType: 'audio/wav', body: wav })) + await page.goto('/test/player.html') + await page.evaluate(() => { + window.nativeAudio = new Audio() + window.nativeAudio.muted = true + window.nativeAudio.src = '/native-wave.wav' + }) + await expect.poll(() => page.evaluate(() => window.nativeAudio.readyState >= 2 || Boolean(window.nativeAudio.error))).toBe(true) + const state = await page.evaluate(() => ({ canPlay: window.nativeAudio.canPlayType('audio/wav'), readyState: window.nativeAudio.readyState, error: window.nativeAudio.error?.code || null, playerCreated: Boolean(window.art) })) + expect(state.playerCreated).toBe(false) + await testInfo.attach('native-wav-capability', { contentType: 'application/json', body: JSON.stringify(state) }) + if (!state.error) { + await page.evaluate(() => window.nativeAudio.play()) + await expect.poll(() => page.evaluate(() => window.nativeAudio.currentTime)).toBeGreaterThan(0.2) + } + else { + expect(state.error).toBe(4) + } + await page.evaluate(() => { + window.nativeAudio.pause() + window.nativeAudio.removeAttribute('src') + window.nativeAudio.load() + }) +}) + +test('published AUDIO-LIFE-01: empty src cleanup produces a native media error', async ({ page }, testInfo) => { + await openAudio(page, 'published', 'published', testInfo) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeGreaterThan(0.2) + await page.evaluate(() => window.art.destroy()) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.error?.code)).toBe(4) + expect(await page.evaluate(() => window.audioPlugin.audio.getAttribute('src'))).toBe('') + expect(await page.evaluate(() => window.audioPlugin.audio.readyState)).toBe(0) +}) + +for (const core of ['published', 'candidate']) { + test(`${core} core + published audio: native pause and end leave external audio playing`, async ({ page }, testInfo) => { + await openAudio(page, core, 'published', testInfo) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeGreaterThan(0.2) + await page.evaluate(() => window.art.video.pause()) + expect(await page.evaluate(() => window.art.video.paused)).toBe(true) + expect(await page.evaluate(() => window.audioPlugin.audio.paused)).toBe(false) + await page.evaluate(() => { + window.art.seek = 7.8 + window.art.play() + }) + await expect.poll(() => page.evaluate(() => window.art.video.ended)).toBe(true) + expect(await page.evaluate(() => window.audioPlugin.audio.paused)).toBe(false) + await testInfo.attach('published-native-pause-end', { contentType: 'application/json', body: JSON.stringify(await page.evaluate(() => ({ videoEnded: window.art.video.ended, videoPaused: window.art.video.paused, audioPaused: window.audioPlugin.audio.paused, audioTime: window.audioPlugin.audio.currentTime }))) }) + await page.evaluate(() => window.art.destroy()) + }) + + for (const plugin of ['published', 'source']) { + test(`${core} core + ${plugin} audio: decoded play, offset seek, rate, source and cleanup`, async ({ page }, testInfo) => { + await openAudio(page, core, plugin, testInfo) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeGreaterThan(0.3) + await expect.poll(() => page.evaluate(() => window.art.currentTime)).toBeGreaterThan(0.3) + expect(await page.evaluate(() => window.audioPlugin.audio.duration)).toBe(16) + // Windows WebKit may expose layout size; decoded pixels are the playback evidence. + const pixel = await page.evaluate(() => { + const canvas = document.createElement('canvas') + canvas.width = 80 + canvas.height = 45 + const context = canvas.getContext('2d') + context.drawImage(window.art.video, 0, 0, 80, 45) + return [...context.getImageData(30, 2, 1, 1).data] + }) + expect(pixel[0]).toBeGreaterThan(180) + expect(pixel[1]).toBeGreaterThan(180) + expect(pixel[2]).toBeLessThan(80) + await testInfo.attach('decoded-frame-pixel', { contentType: 'application/json', body: JSON.stringify(pixel) }) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.seekable.length && window.audioPlugin.audio.seekable.end(0))).toBeGreaterThan(2.25) + await page.evaluate(() => { + window.art.pause() + window.audioPlugin.update({ offset: 0.25 }) + window.art.seek = 2 + }) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.paused)).toBe(true) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeCloseTo(2.25, 1) + await page.evaluate(() => { + window.art.playbackRate = 1.5 + window.art.volume = 0.4 + }) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.playbackRate)).toBe(1.5) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.volume)).toBeCloseTo(0.4) + await page.locator('#play').click() + await page.evaluate(() => { + window.originalAudio = window.audioPlugin.audio + window.audioPlugin.update({ url: '/test/audio-tone.m4a?source=second' }) + }) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentSrc)).toContain('source=second') + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.paused)).toBe(false) + await expect.poll(() => page.evaluate(() => Math.abs(window.audioPlugin.audio.currentTime - window.art.currentTime - 0.25))).toBeLessThan(0.5) + expect(await page.evaluate(() => window.originalAudio === window.audioPlugin.audio)).toBe(true) + await page.evaluate(() => { + window.art.pause() + window.art.destroy() + }) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.readyState)).toBe(0) + expect(await page.evaluate(() => window.audioPlugin.audio.getAttribute('src'))).toBe('') + expect(await page.evaluate(() => window.audioPlugin.audio.paused)).toBe(true) + expect(await page.locator('.art-video-player').count()).toBe(0) + }) + + test(`${core} core + ${plugin} audio: real load error can recover with a new source`, async ({ page }, testInfo) => { + await openAudio(page, core, plugin, testInfo, '') + await page.route('**/audio-fixture/broken.m4a', route => route.fulfill({ status: 503, body: 'Intentional media failure' })) + await page.evaluate(() => window.audioPlugin.update({ url: '/audio-fixture/broken.m4a' })) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.error?.code)).toBe(4) + expect(await page.evaluate(() => window.art.video.error)).toBeNull() + await page.evaluate(() => window.audioPlugin.update({ url: '/test/audio-tone.m4a?source=recovered' })) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.readyState)).toBeGreaterThanOrEqual(2) + await page.locator('#play').click() + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.currentTime)).toBeGreaterThan(0.3) + expect(await page.evaluate(() => window.audioPlugin.audio.error)).toBeNull() + await page.evaluate(() => window.art.destroy()) + await expect.poll(() => page.evaluate(() => window.audioPlugin.audio.readyState)).toBe(0) + expect(await page.evaluate(() => window.audioPlugin.audio.paused)).toBe(true) + expect(await page.evaluate(() => window.audioPlugin.audio.getAttribute('src'))).toBe('') + }) + } +} diff --git a/test/browser/media/audio-tone.json b/test/browser/media/audio-tone.json new file mode 100644 index 000000000..39ab50d0d --- /dev/null +++ b/test/browser/media/audio-tone.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "file": "audio-tone.m4a", + "sha256": "83e6672b880b5d1c97093b1e26bdc40221c0b279615f40e99dbf9d2ade7b4d56", + "bytes": 132436, + "command": "ffmpeg -hide_banner -loglevel error -f lavfi -i sine=frequency=440:sample_rate=48000:duration=16 -ac 1 -c:a aac -b:a 64k -map_metadata -1 -movflags +faststart test/browser/media/audio-tone.m4a", + "ffmpeg": "ffmpeg version 2025-11-12-git-6cdd2cbe32-full_build-www.gyan.dev Copyright (c) 2000-2025 the FFmpeg developers", + "probe": { + "programs": [], + "stream_groups": [], + "streams": [ + { + "codec_name": "aac", + "codec_type": "audio", + "sample_rate": "48000", + "channels": 1 + } + ], + "format": { + "duration": "16.000000" + } + } +} diff --git a/test/browser/media/audio-tone.m4a b/test/browser/media/audio-tone.m4a new file mode 100644 index 000000000..edad923b8 Binary files /dev/null and b/test/browser/media/audio-tone.m4a differ diff --git a/test/browser/server.mjs b/test/browser/server.mjs index d6b5515db..527adfc64 100644 --- a/test/browser/server.mjs +++ b/test/browser/server.mjs @@ -59,8 +59,9 @@ for (const extension of ['mp4', 'webm']) { const name = `test/browser/media/pattern.${extension}` add(`/test/pattern.${extension}`, fs.readFileSync(path.join(workspace, name)), { kind: 'generated-media', file: name }) } +add('/test/audio-tone.m4a', fs.readFileSync(path.join(workspace, 'test/browser/media/audio-tone.m4a')), { kind: 'generated-media', file: 'test/browser/media/audio-tone.m4a' }) -const mime = { '.html': 'text/html', '.js': 'text/javascript', '.mjs': 'text/javascript', '.json': 'application/json', '.css': 'text/css', '.mp4': 'video/mp4', '.webm': 'video/webm', '.vtt': 'text/vtt', '.svg': 'image/svg+xml', '.png': 'image/png', '.jpg': 'image/jpeg' } +const mime = { '.html': 'text/html', '.js': 'text/javascript', '.mjs': 'text/javascript', '.json': 'application/json', '.css': 'text/css', '.mp4': 'video/mp4', '.m4a': 'audio/mp4', '.webm': 'video/webm', '.vtt': 'text/vtt', '.svg': 'image/svg+xml', '.png': 'image/png', '.jpg': 'image/jpeg' } add('/test/declaration-cues.vtt', fs.readFileSync(path.join(workspace, 'test/browser/media/declaration-cues.vtt')), { kind: 'test-subtitles', file: 'test/browser/media/declaration-cues.vtt' }) add('/test/thumbnail-grid.svg', fs.readFileSync(path.join(workspace, 'test/browser/media/thumbnail-grid.svg')), { kind: 'test-thumbnail-grid', file: 'test/browser/media/thumbnail-grid.svg' }) add('/test/legacy-safe-area.js', fs.readFileSync(path.join(workspace, 'test/helpers/legacy-safe-area.js')), { kind: 'frozen-own-source', file: 'test/helpers/legacy-safe-area.js', commit: 'ccf77c4e' }) diff --git a/test/helpers/audio-track.js b/test/helpers/audio-track.js new file mode 100644 index 000000000..8f9179b42 --- /dev/null +++ b/test/helpers/audio-track.js @@ -0,0 +1,99 @@ +import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import fs from 'node:fs' +import vm from 'node:vm' +import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' +import { loadPackage } from './load.js' + +export async function audioImplementations() { + const { release } = JSON.parse(fs.readFileSync(new URL('../../refactor/baselines/audio-track-release.json', import.meta.url))) + const archive = await ensureArchive(release) + const implementations = [{ name: 'source', factory: (await loadPackage(release.name)).default }] + for (const format of ['main', 'legacy', 'module']) { + const member = `package/${release.manifest[format].replace(/^\.\//, '')}` + const bytes = readMember(archive, member) + assert.equal(hash(bytes), release.files[member]) + let factory + if (format === 'module') { + factory = (await import(`data:text/javascript;base64,${Buffer.from(bytes).toString('base64')}`)).default + } + else { + const context = { + module: { exports: {} }, + Audio: function Audio() { + return new globalThis.Audio() + }, + console, + } + context.exports = context.module.exports + vm.runInNewContext(bytes.toString(), context, { timeout: 5000 }) + factory = context.module.exports + } + implementations.push({ name: `published-${format}`, factory }) + } + return implementations +} + +// Records plugin intent only. It does not decode media or emulate browser timing. +export function audioHost(t) { + const instances = [] + const warnings = [] + let play = () => Promise.resolve() + class Audio { + constructor() { + instances.push(this) + this.calls = [] + this.paused = true + for (const [name, initial] of Object.entries({ src: '', preload: '', currentTime: 0, playbackRate: 1, volume: 1, muted: false })) { + let value = initial + Object.defineProperty(this, name, { + get: () => value, + set: (next) => { + this.calls.push([name, next]) + value = next + }, + }) + } + } + + play() { + this.calls.push(['play']) + return play(this) + } + + pause() { this.calls.push(['pause']) } + load() { this.calls.push(['load']) } + } + const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Audio') + Object.defineProperty(globalThis, 'Audio', { configurable: true, value: Audio }) + t.after(() => descriptor ? Object.defineProperty(globalThis, 'Audio', descriptor) : Reflect.deleteProperty(globalThis, 'Audio')) + t.mock.method(console, 'warn', error => warnings.push(error)) + return { ...createAudioArt(), instances, warnings, setPlay: callback => play = callback } +} + +export function createAudioArt() { + const listeners = new Map() + const art = { + video: { playbackRate: 1.25 }, + currentTime: 0, + playing: false, + volume: 0.6, + muted: false, + on(event, callback) { + if (!listeners.has(event)) + listeners.set(event, new Set()) + listeners.get(event).add(callback) + return art + }, + off(event, callback) { + listeners.get(event)?.delete(callback) + return art + }, + emit(event, ...args) { + for (const callback of [...(listeners.get(event) || [])]) + callback(...args) + return art + }, + } + return { art, listeners } +}