mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-30 07:20:59 +00:00
examples: implement stats client
This commit is contained in:
parent
5f98e61c91
commit
f9fb18ae1b
23 changed files with 1596 additions and 0 deletions
4
plugins/examples/webrtcsink-stats/.gitignore
vendored
Normal file
4
plugins/examples/webrtcsink-stats/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/node_modules/
|
||||
/dist/
|
||||
/.vscode/
|
||||
.DS_Store
|
16
plugins/examples/webrtcsink-stats/README.md
Normal file
16
plugins/examples/webrtcsink-stats/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Example web client for webrtcsink-stats-server
|
||||
|
||||
This web client will display live statistics as received through a
|
||||
websocket connected to a `webrtcsink-stats-server`.
|
||||
|
||||
Usage:
|
||||
|
||||
``` shell
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then navigate to `http://localhost:3000/`. Once consumers are connected
|
||||
to the webrtc-sink-stats-server, they should be listed on the page, clicking
|
||||
on any consumer will show a modal with plots for some of the most interesting
|
||||
statistics.
|
13
plugins/examples/webrtcsink-stats/index.html
Normal file
13
plugins/examples/webrtcsink-stats/index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Svelte + TS + Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
919
plugins/examples/webrtcsink-stats/package-lock.json
generated
Normal file
919
plugins/examples/webrtcsink-stats/package-lock.json
generated
Normal file
|
@ -0,0 +1,919 @@
|
|||
{
|
||||
"name": "webrtcsink-stats",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
|
||||
"dev": true
|
||||
},
|
||||
"@fortawesome/free-solid-svg-icons": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.stat": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true
|
||||
},
|
||||
"@nodelib/fs.walk": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@rollup/pluginutils": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz",
|
||||
"integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"estree-walker": "^2.0.1",
|
||||
"picomatch": "^2.2.2"
|
||||
}
|
||||
},
|
||||
"@sveltejs/vite-plugin-svelte": {
|
||||
"version": "1.0.0-next.30",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.30.tgz",
|
||||
"integrity": "sha512-YQqdMxjL1VgSFk4/+IY3yLwuRRapPafPiZTiaGEq1psbJYSNYUWx9F1zMm32GMsnogg3zn99mGJOqe3ld3HZSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rollup/pluginutils": "^4.1.1",
|
||||
"debug": "^4.3.2",
|
||||
"kleur": "^4.1.4",
|
||||
"magic-string": "^0.25.7",
|
||||
"require-relative": "^0.8.7",
|
||||
"svelte-hmr": "^0.14.7"
|
||||
}
|
||||
},
|
||||
"@tsconfig/svelte": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-2.0.1.tgz",
|
||||
"integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz",
|
||||
"integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/pug": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.5.tgz",
|
||||
"integrity": "sha512-LOnASQoeNZMkzexRuyqcBBDZ6rS+rQxUMkmj5A0PkhhiSZivLIuz6Hxyr1mkGoEZEkk66faROmpMi4fFkrKsBA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sass": {
|
||||
"version": "1.43.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz",
|
||||
"integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
|
||||
"dev": true
|
||||
},
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"detect-indent": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
|
||||
"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
|
||||
"dev": true
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.15.tgz",
|
||||
"integrity": "sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild-android-arm64": "0.13.15",
|
||||
"esbuild-darwin-64": "0.13.15",
|
||||
"esbuild-darwin-arm64": "0.13.15",
|
||||
"esbuild-freebsd-64": "0.13.15",
|
||||
"esbuild-freebsd-arm64": "0.13.15",
|
||||
"esbuild-linux-32": "0.13.15",
|
||||
"esbuild-linux-64": "0.13.15",
|
||||
"esbuild-linux-arm": "0.13.15",
|
||||
"esbuild-linux-arm64": "0.13.15",
|
||||
"esbuild-linux-mips64le": "0.13.15",
|
||||
"esbuild-linux-ppc64le": "0.13.15",
|
||||
"esbuild-netbsd-64": "0.13.15",
|
||||
"esbuild-openbsd-64": "0.13.15",
|
||||
"esbuild-sunos-64": "0.13.15",
|
||||
"esbuild-windows-32": "0.13.15",
|
||||
"esbuild-windows-64": "0.13.15",
|
||||
"esbuild-windows-arm64": "0.13.15"
|
||||
}
|
||||
},
|
||||
"esbuild-android-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.15.tgz",
|
||||
"integrity": "sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-darwin-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-freebsd-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-32": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.15.tgz",
|
||||
"integrity": "sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.15.tgz",
|
||||
"integrity": "sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.15.tgz",
|
||||
"integrity": "sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-mips64le": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.15.tgz",
|
||||
"integrity": "sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-linux-ppc64le": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.15.tgz",
|
||||
"integrity": "sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-netbsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-openbsd-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.15.tgz",
|
||||
"integrity": "sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-sunos-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.15.tgz",
|
||||
"integrity": "sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-32": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.15.tgz",
|
||||
"integrity": "sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.15.tgz",
|
||||
"integrity": "sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-windows-arm64": {
|
||||
"version": "0.13.15",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.15.tgz",
|
||||
"integrity": "sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
|
||||
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
"integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
|
||||
"dev": true
|
||||
},
|
||||
"has": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"parent-module": "^1.0.0",
|
||||
"resolve-from": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
|
||||
"integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"kleur": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
|
||||
"integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==",
|
||||
"dev": true
|
||||
},
|
||||
"magic-string": {
|
||||
"version": "0.25.7",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
|
||||
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sourcemap-codec": "^1.4.4"
|
||||
}
|
||||
},
|
||||
"merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
|
||||
"integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"braces": "^3.0.1",
|
||||
"picomatch": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"min-indent": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
|
||||
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.29.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||
},
|
||||
"mri": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
|
||||
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.30",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
|
||||
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"callsites": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
},
|
||||
"picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.4.4",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.4.tgz",
|
||||
"integrity": "sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nanoid": "^3.1.30",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"require-relative": {
|
||||
"version": "0.8.7",
|
||||
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
|
||||
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-core-module": "^2.2.0",
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
||||
"dev": true
|
||||
},
|
||||
"reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.60.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.60.1.tgz",
|
||||
"integrity": "sha512-akwfnpjY0rXEDSn1UTVfKXJhPsEBu+imi1gqBA1ZkHGydUnkV/fWCC90P7rDaLEW8KTwBcS1G3N4893Ndz+jwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"sade": {
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz",
|
||||
"integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mri": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"sander": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
|
||||
"integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es6-promise": "^3.1.2",
|
||||
"graceful-fs": "^4.1.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "^2.5.2"
|
||||
}
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.43.5",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.5.tgz",
|
||||
"integrity": "sha512-WuNm+eAryMgQluL7Mbq9M4EruyGGMyal7Lu58FfnRMVWxgUzIvI7aSn60iNt3kn5yZBMR7G84fAGDcwqOF5JOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": ">=3.0.0 <4.0.0"
|
||||
}
|
||||
},
|
||||
"sorcery": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
|
||||
"integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-crc32": "^0.2.5",
|
||||
"minimist": "^1.2.0",
|
||||
"sander": "^0.5.0",
|
||||
"sourcemap-codec": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map-js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz",
|
||||
"integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==",
|
||||
"dev": true
|
||||
},
|
||||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
|
||||
"integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"min-indent": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"svelte": {
|
||||
"version": "3.44.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.44.2.tgz",
|
||||
"integrity": "sha512-jrZhZtmH3ZMweXg1Q15onb8QlWD+a5T5Oca4C1jYvSURp2oD35h4A5TV6t6MEa93K4LlX6BkafZPdQoFjw/ylA==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte-check": {
|
||||
"version": "2.2.10",
|
||||
"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.2.10.tgz",
|
||||
"integrity": "sha512-UVLd/N7hUIG2v6dytofsw8MxYn2iS2hpNSglsGz9Z9b8ZfbJ5jayl4Mm1SXhNwiFs5aklG90zSBJtd7NTK8dTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.0.0",
|
||||
"chokidar": "^3.4.1",
|
||||
"fast-glob": "^3.2.7",
|
||||
"import-fresh": "^3.2.1",
|
||||
"minimist": "^1.2.5",
|
||||
"sade": "^1.7.4",
|
||||
"source-map": "^0.7.3",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"typescript": "*"
|
||||
}
|
||||
},
|
||||
"svelte-fa": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-fa/-/svelte-fa-2.4.0.tgz",
|
||||
"integrity": "sha512-0bnbMGbsE1LUnlioDcf27tl2O8kjuXlTXMXzIxC7LoIOWmqn0D+zd539HfLiQbdLuOHGTaynwN9V+4ehhEu1Jw==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte-hmr": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.7.tgz",
|
||||
"integrity": "sha512-pDrzgcWSoMaK6AJkBWkmgIsecW0GChxYZSZieIYfCP0v2oPyx2CYU/zm7TBIcjLVUPP714WxmViE9Thht4etog==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte-preprocess": {
|
||||
"version": "4.9.8",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.9.8.tgz",
|
||||
"integrity": "sha512-EQS/oRZzMtYdAprppZxY3HcysKh11w54MgA63ybtL+TAZ4hVqYOnhw41JVJjWN9dhPnNjjLzvbZ2tMhTsla1Og==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/pug": "^2.0.4",
|
||||
"@types/sass": "^1.16.0",
|
||||
"detect-indent": "^6.0.0",
|
||||
"magic-string": "^0.25.7",
|
||||
"sorcery": "^0.10.0",
|
||||
"strip-indent": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.5.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz",
|
||||
"integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==",
|
||||
"dev": true
|
||||
},
|
||||
"vite": {
|
||||
"version": "2.6.14",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.6.14.tgz",
|
||||
"integrity": "sha512-2HA9xGyi+EhY2MXo0+A2dRsqsAG3eFNEVIo12olkWhOmc8LfiM+eMdrXf+Ruje9gdXgvSqjLI9freec1RUM5EA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.13.2",
|
||||
"fsevents": "~2.3.2",
|
||||
"postcss": "^8.3.8",
|
||||
"resolve": "^1.20.0",
|
||||
"rollup": "^2.57.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
27
plugins/examples/webrtcsink-stats/package.json
Normal file
27
plugins/examples/webrtcsink-stats/package.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "webrtcsink-stats",
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.11",
|
||||
"@tsconfig/svelte": "^2.0.1",
|
||||
"sass": "^1.43.5",
|
||||
"svelte": "^3.37.0",
|
||||
"svelte-check": "^2.1.0",
|
||||
"svelte-fa": "^2.4.0",
|
||||
"svelte-preprocess": "^4.7.2",
|
||||
"tslib": "^2.2.0",
|
||||
"typescript": "^4.3.2",
|
||||
"vite": "^2.6.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"moment": "^2.29.1"
|
||||
}
|
||||
}
|
BIN
plugins/examples/webrtcsink-stats/public/favicon.ico
Normal file
BIN
plugins/examples/webrtcsink-stats/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
152
plugins/examples/webrtcsink-stats/src/App.svelte
Normal file
152
plugins/examples/webrtcsink-stats/src/App.svelte
Normal file
|
@ -0,0 +1,152 @@
|
|||
<svelte:head>
|
||||
<script src="https://cdn.plot.ly/plotly-latest.min.js" type="text/javascript"></script>
|
||||
</svelte:head>
|
||||
|
||||
<script lang="ts">
|
||||
import Home from '@/pages/Home.svelte'
|
||||
import Header from '@/components/Header.svelte'
|
||||
import type { ConsumerType } from '@/types/app'
|
||||
import { WebSocketStatus, MitigationMode } from '@/types/app'
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
|
||||
let ws: WebSocket | undefined = undefined
|
||||
let websocketStatus: WebSocketStatus = WebSocketStatus.Connecting
|
||||
let consumers: Map<string, ConsumerType> = new Map ()
|
||||
let consumers_array: Array<ConsumerType> = []
|
||||
let timeout: ReturnType<typeof setTimeout> | undefined = undefined
|
||||
|
||||
const updateConsumerStats = (consumer: ConsumerType, stats: Object) => {
|
||||
if (stats["consumer-stats"]["video-encoders"].length > 0) {
|
||||
let venc = stats["consumer-stats"]["video-encoders"][0]
|
||||
consumer.stats["target_bitrate"] = venc["bitrate"]
|
||||
consumer.video_codec = venc["codec-name"]
|
||||
|
||||
let mitigation_mode = MitigationMode.None
|
||||
|
||||
for (let mode of venc["mitigation-mode"].split("+")) {
|
||||
switch (mode) {
|
||||
case "none": {
|
||||
mitigation_mode |= MitigationMode.None
|
||||
break
|
||||
}
|
||||
case "downscaled": {
|
||||
mitigation_mode |= MitigationMode.Downscaled
|
||||
break
|
||||
}
|
||||
case "downsampled": {
|
||||
mitigation_mode |= MitigationMode.Downsampled
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
consumer.mitigation_mode = mitigation_mode
|
||||
} else {
|
||||
consumer.stats["target_bitrate"] = 0
|
||||
}
|
||||
|
||||
for (let svalue of Object.values(stats)) {
|
||||
if (svalue["type"] == "transport") {
|
||||
let twcc_stats = svalue["gst-twcc-stats"]
|
||||
if (twcc_stats !== undefined) {
|
||||
consumer.stats["bitrate_sent"] = twcc_stats["bitrate-sent"]
|
||||
consumer.stats["bitrate_recv"] = twcc_stats["bitrate-recv"]
|
||||
consumer.stats["packet_loss"] = twcc_stats["packet-loss-pct"]
|
||||
consumer.stats["delta_of_delta"] = twcc_stats["avg-delta-of-delta"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const fetchStats = () => {
|
||||
ws = new WebSocket("ws://127.0.0.1:8484");
|
||||
|
||||
ws.onerror = () => {
|
||||
websocketStatus = WebSocketStatus.Error
|
||||
}
|
||||
|
||||
ws.onclose = () => {
|
||||
websocketStatus = WebSocketStatus.Error
|
||||
consumers = new Map()
|
||||
consumers_array = []
|
||||
timeout = setTimeout(fetchStats, 500)
|
||||
}
|
||||
|
||||
ws.onopen = () => {
|
||||
websocketStatus = WebSocketStatus.Connected
|
||||
}
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
let stats = JSON.parse(event.data)
|
||||
// Set is supposed to be buildable from an iterator,
|
||||
// no idea why the Arra.from is needed ..
|
||||
let to_remove = new Set(Array.from(consumers.keys()))
|
||||
|
||||
for (let [key, value] of Object.entries(stats)) {
|
||||
let consumer = undefined;
|
||||
|
||||
if (consumers.get(key) === undefined) {
|
||||
consumer = {
|
||||
id: key,
|
||||
video_codec: undefined,
|
||||
mitigation_mode: MitigationMode.None,
|
||||
stats: new Map([
|
||||
["target_bitrate", 0],
|
||||
["bitrate_sent", 0],
|
||||
["bitrate_recv", 0],
|
||||
["packet_loss", 0],
|
||||
["delta_of_delta", 0]
|
||||
]),
|
||||
}
|
||||
consumers.set(key, consumer)
|
||||
} else {
|
||||
consumer = consumers.get(key)
|
||||
}
|
||||
|
||||
updateConsumerStats(consumer, value)
|
||||
|
||||
to_remove.delete(key)
|
||||
}
|
||||
|
||||
for (let key of to_remove) {
|
||||
consumers.delete(key)
|
||||
}
|
||||
|
||||
consumers_array = Array.from(consumers.values())
|
||||
}
|
||||
}
|
||||
|
||||
const closeWebSocket = () => {
|
||||
if (ws != undefined) {
|
||||
ws.close();
|
||||
ws = undefined;
|
||||
}
|
||||
|
||||
if (timeout != undefined) {
|
||||
clearTimeout(timeout)
|
||||
timeout = undefined
|
||||
}
|
||||
}
|
||||
|
||||
onMount(fetchStats)
|
||||
onDestroy(closeWebSocket)
|
||||
</script>
|
||||
|
||||
<Header websocketStatus={ websocketStatus } />
|
||||
|
||||
<Home consumers={ consumers_array } />
|
||||
|
||||
<style lang="scss">
|
||||
:root {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
height: 100%;
|
||||
}
|
||||
:global(body) {
|
||||
/* this will apply to <body> */
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
</style>
|
BIN
plugins/examples/webrtcsink-stats/src/assets/h264.png
Normal file
BIN
plugins/examples/webrtcsink-stats/src/assets/h264.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
BIN
plugins/examples/webrtcsink-stats/src/assets/svelte.png
Normal file
BIN
plugins/examples/webrtcsink-stats/src/assets/svelte.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
plugins/examples/webrtcsink-stats/src/assets/vp8.png
Normal file
BIN
plugins/examples/webrtcsink-stats/src/assets/vp8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
plugins/examples/webrtcsink-stats/src/assets/vp9.png
Normal file
BIN
plugins/examples/webrtcsink-stats/src/assets/vp9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
|
@ -0,0 +1,32 @@
|
|||
<script lang="ts">
|
||||
import type { ConsumerType } from '@/types/app'
|
||||
import EncoderProps from '@/components/EncoderProps.svelte'
|
||||
|
||||
export let consumer: ConsumerType
|
||||
|
||||
$: id = consumer.id
|
||||
</script>
|
||||
|
||||
<div class="consumer-card" on:click >
|
||||
<div class="id">{id}</div>
|
||||
<EncoderProps
|
||||
consumer={consumer}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.consumer-card {
|
||||
word-break: break-all;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
margin-right: 15px;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
box-shadow: rgb(0 0 0 / 24%) 0px 3px 8px;
|
||||
.id {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,53 @@
|
|||
<script lang="ts">
|
||||
import type { ConsumerType } from '@/types/app'
|
||||
import { MitigationMode } from '@/types/app'
|
||||
import Fa from 'svelte-fa'
|
||||
import { faExclamationTriangle, faCheckCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import vp8_logo from '@/assets/vp8.png'
|
||||
import vp9_logo from '@/assets/vp9.png'
|
||||
import h264_logo from '@/assets/h264.png'
|
||||
|
||||
export let consumer: ConsumerType
|
||||
|
||||
$: video_codec = consumer.video_codec
|
||||
$: mitigation_mode = consumer.mitigation_mode
|
||||
</script>
|
||||
|
||||
<div class="encoder-props">
|
||||
<div class="codec">
|
||||
{#if video_codec == "video/x-vp8"}
|
||||
<img src={vp8_logo} alt="VP8">
|
||||
{:else if video_codec == "video/x-vp9"}
|
||||
<img src={vp9_logo} alt="VP8">
|
||||
{:else if video_codec == "video/x-h264"}
|
||||
<img src={h264_logo} alt="VP8">
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
{#if mitigation_mode & MitigationMode.Downsampled && mitigation_mode & MitigationMode.Downscaled}
|
||||
<abbr title="Very congested link, video is downscaled and downsampled">
|
||||
<Fa icon={faExclamationTriangle} color="tomato" />
|
||||
</abbr>
|
||||
{:else if mitigation_mode & MitigationMode.Downscaled}
|
||||
<abbr title="Congested link, video is downscaled">
|
||||
<Fa icon={faExclamationTriangle} color="orange" />
|
||||
</abbr>
|
||||
{:else}
|
||||
<abbr title="Link with minimal to no congestion">
|
||||
<Fa icon={faCheckCircle} color="lightseagreen" />
|
||||
</abbr>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.encoder-props {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
.codec {
|
||||
img {
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,48 @@
|
|||
<script lang="ts">
|
||||
import { WebSocketStatus } from '@/types/app'
|
||||
|
||||
import logo from '@/assets/svelte.png'
|
||||
import Fa from 'svelte-fa'
|
||||
import { faSpinner, faExclamationTriangle, faCheckCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export let websocketStatus: WebSocketStatus
|
||||
</script>
|
||||
|
||||
<header class="global-header">
|
||||
<div class="app-name">
|
||||
<img src={logo} alt="Svelte Logo" class="logo"/>
|
||||
<div class="title">WebRTC Stats App</div>
|
||||
<div>
|
||||
{#if websocketStatus == WebSocketStatus.Connected}
|
||||
<Fa icon={faCheckCircle} color="lightseagreen" size="1x" />
|
||||
{:else if websocketStatus == WebSocketStatus.Connecting}
|
||||
<Fa icon={faSpinner} color="#afaeae" size="1x" spin />
|
||||
{:else if websocketStatus == WebSocketStatus.Error}
|
||||
<Fa icon={faExclamationTriangle} color="tomato" size="1x" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style lang="scss">
|
||||
.global-header {
|
||||
background-color: #313131;
|
||||
height: 56px;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
.app-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
.logo {
|
||||
height: 100%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.title {
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,50 @@
|
|||
<script lang="ts">
|
||||
import Fa from 'svelte-fa'
|
||||
import { faTimes } from '@fortawesome/free-solid-svg-icons';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<div class="modal-overlay">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<slot name="title"></slot>
|
||||
<div class="close-icon" on:click="{() => dispatch('closeModal')}">
|
||||
<Fa icon={faTimes} color="#afaeae" size="1x" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<slot name="body"></slot>
|
||||
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.modal {
|
||||
background-color: white;
|
||||
padding: 15px 0;
|
||||
border-radius: 10px;
|
||||
box-shadow: rgb(0 0 0 / 24%) 0px 3px 8px;
|
||||
&-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: rgb(0, 0, 0, 0.4);
|
||||
}
|
||||
&-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 15px 10px;
|
||||
border-bottom: 3px solid #e2e2e2;
|
||||
}
|
||||
.close-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,141 @@
|
|||
<svelte:head>
|
||||
<script src="https://cdn.plot.ly/plotly-latest.min.js" type="text/javascript"></script>
|
||||
</svelte:head>
|
||||
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount, onDestroy } from 'svelte';
|
||||
import Modal from '@/components/Modal.svelte'
|
||||
import type { ConsumerType } from '@/types/app'
|
||||
import EncoderProps from '@/components/EncoderProps.svelte'
|
||||
|
||||
export let consumer: ConsumerType
|
||||
|
||||
$: if (consumer === undefined) {
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
$: id = consumer !== undefined ? consumer.id : undefined
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let interval: ReturnType<typeof setInterval> | undefined = undefined
|
||||
|
||||
onMount(() => {
|
||||
let plotDiv = document.getElementById('plotDiv');
|
||||
|
||||
let traces = []
|
||||
let layout = {
|
||||
legend: {traceorder: 'reversed'},
|
||||
}
|
||||
let ctr = 1;
|
||||
let domain_step = 1.0 / consumer.stats.size
|
||||
let domain_margin = domain_step / consumer.stats.size
|
||||
|
||||
for (let key of consumer.stats.keys()) {
|
||||
let trace = {
|
||||
x: [],
|
||||
y: [],
|
||||
xaxis: 'x' + ctr,
|
||||
yaxis: 'y' + ctr,
|
||||
mode: 'lines',
|
||||
line: {shape: 'spline'},
|
||||
name: key
|
||||
}
|
||||
|
||||
traces.push(trace)
|
||||
|
||||
layout['xaxis' + ctr] = {
|
||||
type: 'date',
|
||||
}
|
||||
|
||||
layout['yaxis' + ctr] = {
|
||||
domain: [(ctr - 1) * domain_step, (ctr * domain_step) - domain_margin],
|
||||
rangemode: "tozero",
|
||||
}
|
||||
|
||||
ctr += 1
|
||||
}
|
||||
|
||||
Plotly.newPlot(plotDiv, traces, layout);
|
||||
|
||||
interval = setInterval(function() {
|
||||
let time = new Date()
|
||||
let ctr = 0
|
||||
let traces = []
|
||||
let data_update = {
|
||||
x: [],
|
||||
y: [],
|
||||
}
|
||||
|
||||
for (let value of Object.values(consumer.stats)) {
|
||||
data_update.x.push([time])
|
||||
data_update.y.push([value])
|
||||
traces.push(ctr)
|
||||
ctr += 1
|
||||
}
|
||||
|
||||
Plotly.extendTraces(plotDiv, data_update, traces, 600)
|
||||
|
||||
}, 50);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
console.log ("destroyed")
|
||||
|
||||
if (interval !== undefined ) {
|
||||
clearInterval (interval)
|
||||
interval = undefined
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<Modal on:closeModal="{() => dispatch('close')}">
|
||||
<div slot="body" class="modal-body">
|
||||
<div class="id">{id}</div>
|
||||
<EncoderProps
|
||||
consumer={consumer}
|
||||
/>
|
||||
<div id="plotDiv"></div>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="modal-footer">
|
||||
<div class="buttons-wrapper">
|
||||
<button
|
||||
class="button"
|
||||
on:click|stopPropagation="{() => dispatch('close')}"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<style lang="scss">
|
||||
.modal {
|
||||
&-body {
|
||||
width: 700px;
|
||||
padding: 20px 15px 10px;
|
||||
gap: 15px 0;
|
||||
.id {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
&-footer {
|
||||
padding: 0 15px;
|
||||
.buttons-wrapper {
|
||||
text-align: right;
|
||||
}
|
||||
.button {
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
text-align: center;
|
||||
box-sizing: content-box;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #000;
|
||||
&:active {
|
||||
background-color: #b9b7b7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
7
plugins/examples/webrtcsink-stats/src/main.ts
Normal file
7
plugins/examples/webrtcsink-stats/src/main.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import App from './App.svelte'
|
||||
|
||||
const app = new App({
|
||||
target: document.getElementById('app')
|
||||
})
|
||||
|
||||
export default app
|
64
plugins/examples/webrtcsink-stats/src/pages/Home.svelte
Normal file
64
plugins/examples/webrtcsink-stats/src/pages/Home.svelte
Normal file
|
@ -0,0 +1,64 @@
|
|||
<script lang="ts">
|
||||
import type { ConsumerType } from '@/types/app'
|
||||
import Consumer from '@/components/Consumer.svelte'
|
||||
import PlotConsumerModal from '@/components/PlotConsumerModal.svelte'
|
||||
|
||||
export let consumers: Array<ConsumerType>
|
||||
|
||||
let consumerToPlot: ConsumerType | undefined
|
||||
let showPlotModal = false
|
||||
|
||||
/**
|
||||
* Display the Plot modal
|
||||
*
|
||||
* @param {ConsumerType} consumer
|
||||
*/
|
||||
const openPlotConsumer = (consumer: ConsumerType) => {
|
||||
consumerToPlot = consumer
|
||||
showPlotModal = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the Plot modal
|
||||
*
|
||||
*/
|
||||
const closePlotConsumer = () => {
|
||||
consumerToPlot = undefined
|
||||
showPlotModal = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div class="consumer-card-container">
|
||||
{#each consumers as consumer}
|
||||
<Consumer
|
||||
consumer = {consumer}
|
||||
on:click="{() => { openPlotConsumer(consumer) }}"
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{#if showPlotModal}
|
||||
<PlotConsumerModal
|
||||
consumer={consumers.find(consumer => consumer == consumerToPlot)}
|
||||
on:close="{closePlotConsumer}"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
main {
|
||||
padding: 2em;
|
||||
margin: 0 auto;
|
||||
width: 100vw;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.consumer-card {
|
||||
&-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
row-gap: 20px;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
</style>
|
18
plugins/examples/webrtcsink-stats/src/types/app.ts
Normal file
18
plugins/examples/webrtcsink-stats/src/types/app.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
export enum MitigationMode {
|
||||
None = 0,
|
||||
Downscaled = 1,
|
||||
Downsampled = 2,
|
||||
}
|
||||
|
||||
export interface ConsumerType {
|
||||
id: string,
|
||||
video_codec: string | undefined,
|
||||
mitigation_mode: MitigationMode,
|
||||
stats: Map<string, number>,
|
||||
}
|
||||
|
||||
export enum WebSocketStatus {
|
||||
Connecting = 0,
|
||||
Connected = 1,
|
||||
Error = 2,
|
||||
}
|
2
plugins/examples/webrtcsink-stats/src/vite-env.d.ts
vendored
Normal file
2
plugins/examples/webrtcsink-stats/src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/// <reference types="svelte" />
|
||||
/// <reference types="vite/client" />
|
13
plugins/examples/webrtcsink-stats/svelte.config.js
Normal file
13
plugins/examples/webrtcsink-stats/svelte.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import sveltePreprocess from 'svelte-preprocess'
|
||||
import * as sass from 'sass'
|
||||
|
||||
export default {
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: sveltePreprocess({
|
||||
sass: {
|
||||
sync: true,
|
||||
implementation: sass,
|
||||
},
|
||||
})
|
||||
}
|
24
plugins/examples/webrtcsink-stats/tsconfig.json
Normal file
24
plugins/examples/webrtcsink-stats/tsconfig.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"baseUrl": ".",
|
||||
/**
|
||||
* Typechecking JS in `.svelte` and `.js` files by default.
|
||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||
* Note that setting allowJs false does not prevent the use
|
||||
* of JS in `.svelte` files.
|
||||
*/
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
],
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
||||
}
|
13
plugins/examples/webrtcsink-stats/vite.config.js
Normal file
13
plugins/examples/webrtcsink-stats/vite.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
import path from 'path';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [svelte()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve('/src'),
|
||||
},
|
||||
}
|
||||
})
|
Loading…
Reference in a new issue