mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-15 17:16:16 -08:00
test(asr): [PKG-ASR-05] checkpoint local editor and adjacent core coverage
This commit is contained in:
1 parent
6d7b9292f8
commit
2cede66933
18 files changed
+10908
-240
No files matched your search
@@ -0,0 +1,92 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import fs from 'node:fs'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Demo lifecycle uses the repository runner.
|
||||
import test from 'node:test'
|
||||
import vm from 'node:vm'
|
||||
import { deferredAudio } from './helpers/asr-audio.js'
|
||||
|
||||
const code = fs.readFileSync(new URL('../docs/assets/example/asr.local.js', import.meta.url), 'utf8')
|
||||
|
||||
function example() {
|
||||
const requests = []
|
||||
const statistics = { textContent: '' }
|
||||
let instance
|
||||
let option
|
||||
let asrOption
|
||||
const stop = deferredAudio()
|
||||
function forbidden(...args) {
|
||||
requests.push(args)
|
||||
throw new Error('The local ASR example must not open a recognition connection')
|
||||
}
|
||||
const context = vm.createContext({
|
||||
document: { createElement: () => statistics },
|
||||
Artplayer: class {
|
||||
isDestroy = false
|
||||
plugins = { artplayerPluginAsr: { stop: () => stop.promise } }
|
||||
constructor(value) {
|
||||
option = value
|
||||
instance = this
|
||||
}
|
||||
},
|
||||
artplayerPluginAsr(value) {
|
||||
asrOption = value
|
||||
return () => ({ name: 'artplayerPluginAsr' })
|
||||
},
|
||||
fetch: forbidden,
|
||||
WebSocket: forbidden,
|
||||
XMLHttpRequest: forbidden,
|
||||
EventSource: forbidden,
|
||||
navigator: { sendBeacon: forbidden },
|
||||
})
|
||||
vm.runInContext(code, context, { timeout: 1000 })
|
||||
return { statistics, instance, option, asrOption, requests, stop }
|
||||
}
|
||||
|
||||
function chunk() {
|
||||
const pcm = new ArrayBuffer(8000)
|
||||
const wav = new ArrayBuffer(8044)
|
||||
const samples = new DataView(pcm)
|
||||
samples.setInt16(0, -32768, true)
|
||||
samples.setInt16(2, 32767, true)
|
||||
new DataView(wav).setUint32(24, 16000, true)
|
||||
return { pcm, wav }
|
||||
}
|
||||
|
||||
test('ASR local example uses a real same-site sample and reports PCM/WAV without a recognition connection', () => {
|
||||
const environment = example()
|
||||
assert.equal(environment.option.url, '/assets/sample/steve-jobs.mp4')
|
||||
assert.ok(fs.statSync(new URL(`../docs${environment.option.url}`, import.meta.url)).size > 0)
|
||||
assert.equal(environment.option.layers[0].html, environment.statistics)
|
||||
assert.equal(environment.asrOption.interval, 250)
|
||||
assert.equal(environment.asrOption.onAudioChunk(chunk()), 'Simulated local subtitle: audio chunk 1 received.')
|
||||
assert.match(environment.statistics.textContent, /Chunks: 1 \| 16000 Hz mono PCM16 \| 0\.25 seconds captured/u)
|
||||
assert.match(environment.statistics.textContent, /PCM: 8000 bytes \| WAV: 8044 bytes \| Current peak: 32768/u)
|
||||
environment.asrOption.onAudioChunk(chunk())
|
||||
assert.match(environment.statistics.textContent, /Chunks: 2.*0\.50 seconds captured/u)
|
||||
assert.match(environment.statistics.textContent, /simulated subtitles, no speech recognition/u)
|
||||
assert.deepEqual(environment.requests, [])
|
||||
})
|
||||
|
||||
test('ASR local example waits for stop and reports how to resume capture', async () => {
|
||||
const environment = example()
|
||||
environment.asrOption.onAudioChunk(chunk())
|
||||
const before = environment.statistics.textContent
|
||||
const stopping = environment.option.controls[0].click()
|
||||
assert.equal(environment.statistics.textContent, before)
|
||||
environment.stop.resolve()
|
||||
await stopping
|
||||
assert.equal(environment.statistics.textContent, 'Local capture stopped. Pause and play to restart. Nothing was uploaded.')
|
||||
assert.deepEqual(environment.requests, [])
|
||||
})
|
||||
|
||||
test('ASR local example ignores late audio and stop completion after player destruction', async () => {
|
||||
const environment = example()
|
||||
const stopping = environment.option.controls[0].click()
|
||||
const before = environment.statistics.textContent
|
||||
environment.instance.isDestroy = true
|
||||
assert.equal(environment.asrOption.onAudioChunk(chunk()), undefined)
|
||||
environment.stop.resolve()
|
||||
await stopping
|
||||
assert.equal(environment.statistics.textContent, before)
|
||||
assert.deepEqual(environment.requests, [])
|
||||
})
|
||||
@@ -13,7 +13,7 @@ test.beforeAll(async () => {
|
||||
})
|
||||
|
||||
for (const version of ['2.0.0', '2.1.0', 'candidate']) {
|
||||
for (const core of ['published', 'candidate']) {
|
||||
for (const core of ['published-5.3.0', 'published', 'candidate']) {
|
||||
test(`ASR ${version} + ${core}: native Worklet supplies local PCM with owned stop and destroy`, async ({ page }, testInfo) => {
|
||||
const release = [contract.baseline.release, ...contract.baseline.previous].find(release => release.version === version)
|
||||
const code = version === 'candidate' ? candidateCode : readMember(contract.archives.get(version), 'package/dist/artplayer-plugin-asr.js')
|
||||
|
||||
@@ -13,7 +13,7 @@ test.beforeAll(async () => {
|
||||
})
|
||||
|
||||
for (const version of ['2.1.0', 'candidate']) {
|
||||
for (const core of ['published', 'candidate']) {
|
||||
for (const core of ['published-5.3.0', 'published', 'candidate']) {
|
||||
test(`ASR ${version} + ${core}: native capture fallback does not create a second audible route`, async ({ page }, testInfo) => {
|
||||
const code = version === 'candidate' ? candidateCode : readMember(contract.archives.get(version), 'package/dist/artplayer-plugin-asr.js')
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
|
||||
@@ -13,7 +13,7 @@ test.beforeAll(async () => {
|
||||
})
|
||||
|
||||
for (const version of ['2.1.0', 'candidate']) {
|
||||
for (const core of ['published', 'candidate']) {
|
||||
for (const core of ['published-5.3.0', 'published', 'candidate']) {
|
||||
test(`ASR ${version} + ${core}: native playback volume and mute`, async ({ page }, testInfo) => {
|
||||
const code = version === 'candidate' ? candidateCode : readMember(contract.archives.get(version), 'package/dist/artplayer-plugin-asr.js')
|
||||
await page.goto(`/test/player.html?core=${core}`)
|
||||
|
||||
@@ -74,6 +74,11 @@ const iframeCoreMember = `package/${iframeCore.manifest.main}`
|
||||
const iframeCoreBytes = readMember(await ensureArchive(iframeCore), iframeCoreMember)
|
||||
assert.equal(hash(iframeCoreBytes), iframeCore.files[iframeCoreMember], 'Historical Iframe core differs from frozen release')
|
||||
add('/published-4.5.9/artplayer.js', iframeCoreBytes, { kind: 'npm-release', version: iframeCore.version, integrity: iframeCore.integrity, member: iframeCoreMember })
|
||||
const asrCore = JSON.parse(fs.readFileSync(path.join(workspace, 'refactor/baselines/asr-core.json'), 'utf8')).release
|
||||
const asrCoreMember = `package/${asrCore.manifest.main.replace(/^\.\//, '')}`
|
||||
const asrCoreBytes = readMember(await ensureArchive(asrCore), asrCoreMember)
|
||||
assert.equal(hash(asrCoreBytes), asrCore.files[asrCoreMember], 'Adjacent stable ASR core differs from frozen release')
|
||||
add('/published-5.3.0/artplayer.js', asrCoreBytes, { kind: 'npm-release', version: asrCore.version, integrity: asrCore.integrity, member: asrCoreMember })
|
||||
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' })
|
||||
add('/test/thumbnail-pattern.mp4', fs.readFileSync(path.join(workspace, 'test/browser/media/thumbnail-pattern.mp4')), { kind: 'generated-media', file: 'test/browser/media/thumbnail-pattern.mp4' })
|
||||
add('/test/auto-thumbnail-timeline.mp4', fs.readFileSync(path.join(workspace, 'test/browser/media/auto-thumbnail-timeline.mp4')), { kind: 'generated-media', file: 'test/browser/media/auto-thumbnail-timeline.mp4' })
|
||||
@@ -145,7 +150,7 @@ const server = http.createServer((req, res) => {
|
||||
if (url.pathname === '/test/player.html') {
|
||||
const core = url.searchParams.get('core') || 'candidate'
|
||||
const chapter = url.searchParams.get('chapter') || 'candidate'
|
||||
assert(['candidate', 'published', 'published-4.5.5', 'published-4.5.9', 'published-5.1.7'].includes(core) && ['candidate', 'published'].includes(chapter), 'Invalid test combination')
|
||||
assert(['candidate', 'published', 'published-4.5.5', 'published-4.5.9', 'published-5.1.7', 'published-5.3.0'].includes(core) && ['candidate', 'published'].includes(chapter), 'Invalid test combination')
|
||||
const html = fs.readFileSync(path.join(workspace, 'test/browser/player.html'), 'utf8')
|
||||
.replace('__CORE__', core)
|
||||
.replace('__CHAPTER__', chapter)
|
||||
|
||||
Reference in new issue
Block a user