diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml
index 3d4891b..6bfe8cc 100644
--- a/.github/workflows/deploy-docs.yml
+++ b/.github/workflows/deploy-docs.yml
@@ -1,10 +1,8 @@
-
name: 部署文档
on:
push:
branches:
- # 确保这是你正在使用的分支名称
- main
permissions:
@@ -15,33 +13,30 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- # 如果你文档需要 Git 子模块,取消注释下一行
- # submodules: true
-
+ - name: 安装 pnpm
+ uses: pnpm/action-setup@v2
+ with:
+ run_install: true
- name: 设置 Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
- node-version: 18
- cache: npm
-
- - name: 安装依赖
- run: npm ci
+ node-version: 20
+ cache: pnpm
- name: 构建文档
env:
NODE_OPTIONS: --max_old_space_size=8192
run: |-
- npm run docs:build
+ pnpm docs:build
> src/.vuepress/dist/.nojekyll
- name: 部署文档
uses: JamesIves/github-pages-deploy-action@v4
with:
- # 这是文档部署到的分支名称
branch: gh-pages
folder: src/.vuepress/dist
diff --git a/README.md b/README.md
index 6f77852..d1dafcc 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
-# docs
+# ZLMediaKit Docs
+
Official documentation for ZLMediaKit
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index e46032c..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,10531 +0,0 @@
-{
- "name": "zlm_docs",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "zlm_docs",
- "version": "1.0.0",
- "license": "MIT",
- "devDependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vuepress": "2.0.0-beta.67",
- "vuepress-theme-hope": "2.0.0-beta.237"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.2.1",
- "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.2.1.tgz",
- "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.22.13",
- "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.22.13.tgz",
- "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.22.13",
- "chalk": "^2.4.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/code-frame/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/code-frame/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/code-frame/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/code-frame/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/@babel/code-frame/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/code-frame/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.22.20.tgz",
- "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.0.tgz",
- "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.22.13",
- "@babel/generator": "^7.23.0",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-module-transforms": "^7.23.0",
- "@babel/helpers": "^7.23.0",
- "@babel/parser": "^7.23.0",
- "@babel/template": "^7.22.15",
- "@babel/traverse": "^7.23.0",
- "@babel/types": "^7.23.0",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.23.0.tgz",
- "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.23.0",
- "@jridgewell/gen-mapping": "^0.3.2",
- "@jridgewell/trace-mapping": "^0.3.17",
- "jsesc": "^2.5.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
- "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.15"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
- "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-validator-option": "^7.22.15",
- "browserslist": "^4.21.9",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
- "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-member-expression-to-functions": "^7.22.15",
- "@babel/helper-optimise-call-expression": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz",
- "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "regexpu-core": "^5.3.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.4.2",
- "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz",
- "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.22.6",
- "@babel/helper-plugin-utils": "^7.22.5",
- "debug": "^4.1.1",
- "lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
- "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
- "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.22.15",
- "@babel/types": "^7.23.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-hoist-variables": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
- "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
- "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.23.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
- "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.15"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
- "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/helper-simple-access": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/helper-validator-identifier": "^7.22.20"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz",
- "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
- "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz",
- "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-wrap-function": "^7.22.20"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz",
- "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-member-expression-to-functions": "^7.22.15",
- "@babel/helper-optimise-call-expression": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-simple-access": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
- "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz",
- "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
- "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
- "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
- "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-wrap-function": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz",
- "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-function-name": "^7.22.5",
- "@babel/template": "^7.22.15",
- "@babel/types": "^7.22.19"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.23.1",
- "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.23.1.tgz",
- "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.22.15",
- "@babel/traverse": "^7.23.0",
- "@babel/types": "^7.23.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.22.20.tgz",
- "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.22.20",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/@babel/highlight/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.23.0.tgz",
- "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
- "dev": true,
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz",
- "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz",
- "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/plugin-transform-optional-chaining": "^7.22.15"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.13.0"
- }
- },
- "node_modules/@babel/plugin-proposal-private-property-in-object": {
- "version": "7.21.0-placeholder-for-preset-env.2",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
- "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.3"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-assertions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz",
- "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz",
- "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
- "version": "7.18.6",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
- "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.18.6",
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz",
- "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz",
- "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.9",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz",
- "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-imports": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-remap-async-to-generator": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz",
- "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz",
- "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz",
- "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz",
- "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.22.11",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-class-static-block": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.12.0"
- }
- },
- "node_modules/@babel/plugin-transform-classes": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz",
- "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-environment-visitor": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-optimise-call-expression": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.9",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz",
- "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/template": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz",
- "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz",
- "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz",
- "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz",
- "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz",
- "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz",
- "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz",
- "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-function-name": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz",
- "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.22.5",
- "@babel/helper-function-name": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-json-strings": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz",
- "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz",
- "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz",
- "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz",
- "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.0.tgz",
- "integrity": "sha512-xWT5gefv2HGSm4QHtgc1sYPbseOyf+FFDo2JbpE25GWl5BqTGO9IMwTYJRoIdjsF85GE+VegHxSCUt5EvoYTAw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.23.0",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz",
- "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.23.0",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-simple-access": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.0.tgz",
- "integrity": "sha512-qBej6ctXZD2f+DhlOC9yO47yEYgUh5CZNz/aBoH4j/3NOlRfJXJbY7xDQCqQVf9KbrqGzIWER1f23doHGrIHFg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-module-transforms": "^7.23.0",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.20"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz",
- "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-transforms": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz",
- "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-new-target": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz",
- "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz",
- "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz",
- "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz",
- "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.22.9",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.22.15"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-super": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz",
- "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-replace-supers": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz",
- "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.0.tgz",
- "integrity": "sha512-sBBGXbLJjxTzLBF5rFWaikMnOGOk/BmK6vVByIdEggZ7Vn6CvWXZyRkkLFK6WE0IF8jSliyOkUN6SScFgzCM0g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-parameters": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz",
- "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz",
- "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-property-in-object": {
- "version": "7.22.11",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz",
- "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-create-class-features-plugin": "^7.22.11",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz",
- "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.22.10",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz",
- "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "regenerator-transform": "^0.15.2"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz",
- "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz",
- "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-spread": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz",
- "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz",
- "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz",
- "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz",
- "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.22.10",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz",
- "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-property-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz",
- "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz",
- "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.22.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz",
- "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.22.5",
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/preset-env": {
- "version": "7.22.20",
- "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.22.20.tgz",
- "integrity": "sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.22.20",
- "@babel/helper-compilation-targets": "^7.22.15",
- "@babel/helper-plugin-utils": "^7.22.5",
- "@babel/helper-validator-option": "^7.22.15",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15",
- "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-import-assertions": "^7.22.5",
- "@babel/plugin-syntax-import-attributes": "^7.22.5",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5",
- "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.22.5",
- "@babel/plugin-transform-async-generator-functions": "^7.22.15",
- "@babel/plugin-transform-async-to-generator": "^7.22.5",
- "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
- "@babel/plugin-transform-block-scoping": "^7.22.15",
- "@babel/plugin-transform-class-properties": "^7.22.5",
- "@babel/plugin-transform-class-static-block": "^7.22.11",
- "@babel/plugin-transform-classes": "^7.22.15",
- "@babel/plugin-transform-computed-properties": "^7.22.5",
- "@babel/plugin-transform-destructuring": "^7.22.15",
- "@babel/plugin-transform-dotall-regex": "^7.22.5",
- "@babel/plugin-transform-duplicate-keys": "^7.22.5",
- "@babel/plugin-transform-dynamic-import": "^7.22.11",
- "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
- "@babel/plugin-transform-export-namespace-from": "^7.22.11",
- "@babel/plugin-transform-for-of": "^7.22.15",
- "@babel/plugin-transform-function-name": "^7.22.5",
- "@babel/plugin-transform-json-strings": "^7.22.11",
- "@babel/plugin-transform-literals": "^7.22.5",
- "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
- "@babel/plugin-transform-member-expression-literals": "^7.22.5",
- "@babel/plugin-transform-modules-amd": "^7.22.5",
- "@babel/plugin-transform-modules-commonjs": "^7.22.15",
- "@babel/plugin-transform-modules-systemjs": "^7.22.11",
- "@babel/plugin-transform-modules-umd": "^7.22.5",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
- "@babel/plugin-transform-new-target": "^7.22.5",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
- "@babel/plugin-transform-numeric-separator": "^7.22.11",
- "@babel/plugin-transform-object-rest-spread": "^7.22.15",
- "@babel/plugin-transform-object-super": "^7.22.5",
- "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
- "@babel/plugin-transform-optional-chaining": "^7.22.15",
- "@babel/plugin-transform-parameters": "^7.22.15",
- "@babel/plugin-transform-private-methods": "^7.22.5",
- "@babel/plugin-transform-private-property-in-object": "^7.22.11",
- "@babel/plugin-transform-property-literals": "^7.22.5",
- "@babel/plugin-transform-regenerator": "^7.22.10",
- "@babel/plugin-transform-reserved-words": "^7.22.5",
- "@babel/plugin-transform-shorthand-properties": "^7.22.5",
- "@babel/plugin-transform-spread": "^7.22.5",
- "@babel/plugin-transform-sticky-regex": "^7.22.5",
- "@babel/plugin-transform-template-literals": "^7.22.5",
- "@babel/plugin-transform-typeof-symbol": "^7.22.5",
- "@babel/plugin-transform-unicode-escapes": "^7.22.10",
- "@babel/plugin-transform-unicode-property-regex": "^7.22.5",
- "@babel/plugin-transform-unicode-regex": "^7.22.5",
- "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
- "@babel/preset-modules": "0.1.6-no-external-plugins",
- "@babel/types": "^7.22.19",
- "babel-plugin-polyfill-corejs2": "^0.4.5",
- "babel-plugin-polyfill-corejs3": "^0.8.3",
- "babel-plugin-polyfill-regenerator": "^0.5.2",
- "core-js-compat": "^3.31.0",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-modules": {
- "version": "0.1.6-no-external-plugins",
- "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
- "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@babel/types": "^7.4.4",
- "esutils": "^2.0.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/@babel/regjsgen": {
- "version": "0.8.0",
- "resolved": "https://registry.npmmirror.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
- "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==",
- "dev": true
- },
- "node_modules/@babel/runtime": {
- "version": "7.23.1",
- "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.23.1.tgz",
- "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==",
- "dev": true,
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.22.15",
- "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.22.15.tgz",
- "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.22.13",
- "@babel/parser": "^7.22.15",
- "@babel/types": "^7.22.15"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.23.0.tgz",
- "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.22.13",
- "@babel/generator": "^7.23.0",
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-function-name": "^7.23.0",
- "@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.23.0",
- "@babel/types": "^7.23.0",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.23.0",
- "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.23.0.tgz",
- "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-string-parser": "^7.22.5",
- "@babel/helper-validator-identifier": "^7.22.20",
- "to-fast-properties": "^2.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@braintree/sanitize-url": {
- "version": "6.0.4",
- "resolved": "https://registry.npmmirror.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz",
- "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==",
- "dev": true
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
- "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
- "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
- "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
- "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
- "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
- "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
- "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
- "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
- "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
- "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
- "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
- "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
- "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
- "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
- "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
- "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
- "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
- "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
- "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
- "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
- "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
- "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.5",
- "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.5.tgz",
- "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.15",
- "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.19",
- "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@kurkle/color": {
- "version": "0.3.2",
- "resolved": "https://registry.npmmirror.com/@kurkle/color/-/color-0.3.2.tgz",
- "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==",
- "dev": true
- },
- "node_modules/@lit-labs/ssr-dom-shim": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.1.tgz",
- "integrity": "sha512-kXOeFbfCm4fFf2A3WwVEeQj55tMZa8c8/f9AKHMobQMkzNUfUj+antR3fRPaZJawsa1aZiP/Da3ndpZrwEe4rQ==",
- "dev": true
- },
- "node_modules/@lit/reactive-element": {
- "version": "1.6.3",
- "resolved": "https://registry.npmmirror.com/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
- "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
- "dev": true,
- "dependencies": {
- "@lit-labs/ssr-dom-shim": "^1.0.0"
- }
- },
- "node_modules/@maverick-js/signals": {
- "version": "5.11.4",
- "resolved": "https://registry.npmmirror.com/@maverick-js/signals/-/signals-5.11.4.tgz",
- "integrity": "sha512-fkUqNfnJK1kgfsKimaLp2jcfQr7NXwHZWBhqhQ3pifnYSZrBJv+4tU/klKyGf1mA33mVBYustCAgilJppzGjig==",
- "dev": true
- },
- "node_modules/@mdit-vue/plugin-component": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-component/-/plugin-component-0.12.1.tgz",
- "integrity": "sha512-L3elbvuKUufXwPLHrmJGd/ijd/QKxfcHXy3kRy4O+P7UIV7HSWePpfB0k+wWee+by3MviYYxjVAi392z+DGy3Q==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/plugin-frontmatter": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-frontmatter/-/plugin-frontmatter-0.12.1.tgz",
- "integrity": "sha512-C6ycNjrJ+T4JgbVxwo9cUkfLacOO841Yl8ogqd5PJmAVpc5cM2OLBkqqkZxNRXos3g9xM1VvIQ7gK/047UNADg==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "gray-matter": "^4.0.3",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/plugin-headers": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-headers/-/plugin-headers-0.12.1.tgz",
- "integrity": "sha512-DXAw/iWW8f3qUYMDHgQmamL+XGjnaoeRzdvDseLRyr7gXX4xpYO9OIhe/pv9LzSvUoY7UGYmn4kFeI+0qpWJ+g==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/shared": "0.12.1",
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/plugin-sfc": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-sfc/-/plugin-sfc-0.12.1.tgz",
- "integrity": "sha512-6j332CsSqumy1+StIM3XphdXG1zj9NXuWestDJrKgS3OLy5P0EAioXScUYiZYysw61ZG+2pP37MW7Hg+eHbyIg==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/plugin-title": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-title/-/plugin-title-0.12.1.tgz",
- "integrity": "sha512-JOsiDj+CryGbrTDWUnDAwB9kSkN6o9GDo3udR6BPDgBNVb3zAnx9ZNaRpEhDW1LnQhf9/LYicWJ2eTNRKPcJNQ==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/shared": "0.12.1",
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/plugin-toc": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/plugin-toc/-/plugin-toc-0.12.1.tgz",
- "integrity": "sha512-nFGwTwVa8GLCKJMV7cGST7lYuljSjEiCTPgKIpQ/WifwouHsQaL/rnBDr22kpzY2hRTAhM3+TT5GDwLyxa/e6A==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/shared": "0.12.1",
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/shared": {
- "version": "0.12.1",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/shared/-/shared-0.12.1.tgz",
- "integrity": "sha512-bXgd0KThe4jC2leCFDFsyrudXIckvTwV4WnQK/rRMrXq0/BAuVdSNdIv1LGCWZxD5+oDyPyEPd0lalTIFwqsmg==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/types": "0.12.0",
- "@types/markdown-it": "^13.0.0",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit-vue/types": {
- "version": "0.12.0",
- "resolved": "https://registry.npmmirror.com/@mdit-vue/types/-/types-0.12.0.tgz",
- "integrity": "sha512-mrC4y8n88BYvgcgzq9bvTlDgFyi2zuvzmPilRvRc3Uz1iIvq8mDhxJ0rHKFUNzPEScpDvJdIujqiDrulMqiudA==",
- "dev": true
- },
- "node_modules/@mdit/plugin-align": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-align/-/plugin-align-0.4.8.tgz",
- "integrity": "sha512-n6dNMqXb2wZmQ2dod8fq18ehEq+KtMNFoDpC6H3oCaAv/kXT7fYSry0fqrFBP5I3l8yevrgAwo+zZC+c3cyZig==",
- "dev": true,
- "dependencies": {
- "@mdit/plugin-container": "0.4.8",
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-align/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-attrs": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-attrs/-/plugin-attrs-0.4.8.tgz",
- "integrity": "sha512-SB2yTHRNG8j5shh1TtJAPuPFWaMeQp6P/9ieLVPFdXLU6RPobEwf1GAX39YDaIKaWXEmkEJJdKFClOKmyWd9BQ==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-attrs/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-container": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-container/-/plugin-container-0.4.8.tgz",
- "integrity": "sha512-ruiP9XrJ6Uaru/9ZO7iBGm96Fiqr/4Ecn6zHER3/GzWpRJ9oPjrDBWoQ9eFrmINoq1C89puZG0lmAJJ9KCTeAw==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-container/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-figure": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-figure/-/plugin-figure-0.4.8.tgz",
- "integrity": "sha512-fzFwKlE34pnenqAshqHtCrgv5Ro9QE0Cjd0BR/wxkFCy4ZyyVHZUNA007HOz/j9t5ryVimdZQPcqfcQEcBk8sA==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-figure/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-footnote": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-footnote/-/plugin-footnote-0.4.8.tgz",
- "integrity": "sha512-D2OOOoiMEdgI4p5NAtAK8wjOK3th4qIB6ZkOZ38USN+nzTwNy51Prq/elKiqhEd95q0BtWobrPsrY7qO1BW7kA==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-footnote/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-img-lazyload": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-img-lazyload/-/plugin-img-lazyload-0.4.8.tgz",
- "integrity": "sha512-GGppqJQhl5pZ2CftLxstxMVSZQCdOiJB/1aKEMjpi+EehYV1MlKPzaQp+XTyVDJAkv/k6pe+91ZnsSZgHnIUcA==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-img-lazyload/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-img-mark": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-img-mark/-/plugin-img-mark-0.4.8.tgz",
- "integrity": "sha512-00zkJ3cIW1R5O+lk/WHuhOrHFdO17TVVxfBN8mhzH6S17W+2KqBMcBv5fpxi7g3R95rZ1fAZ6T1I5lg069RBkA==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-img-mark/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-img-size": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-img-size/-/plugin-img-size-0.4.8.tgz",
- "integrity": "sha512-+fkNRrhkwZgIRJi6ucginEzy95pmhekOer23gBbOOezZev9D4XpA1tFhLAu1srvUVAKh+JmRXiVJUT71Xw9LTg==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-img-size/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-include": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-include/-/plugin-include-0.4.8.tgz",
- "integrity": "sha512-Hd+ZjisjjUS6ZRtjXUkfbYx3HpGKAY4XVpzmvhinK4+EPqiW4SrQor4G03ckpYu2fFjBF6u6+NbMtkHD8dcMZQ==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1",
- "upath": "^2.0.1"
- }
- },
- "node_modules/@mdit/plugin-include/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-katex": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-katex/-/plugin-katex-0.4.8.tgz",
- "integrity": "sha512-IQUfqpRp+/0gq0VDUOLI0xVvAaiHQv91f6PFBuRG2mvxSsJBECCWZTiJpCgriL7XHSVeSI8zHEYsha9UR674nw==",
- "dev": true,
- "dependencies": {
- "@mdit/plugin-tex": "0.4.8",
- "@types/katex": "^0.16.0",
- "@types/markdown-it": "^12.2.3",
- "katex": "^0.16.7",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-katex/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-mark": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-mark/-/plugin-mark-0.4.8.tgz",
- "integrity": "sha512-51sV7MsPPoW+oa47mwUoD44a3N6XcnYBCOixuDtPzpmKH7ueUJ/ULOGJoBsbveo/ZqTCivJ+3cwoTujaGua8mQ==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-mark/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-mathjax": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-mathjax/-/plugin-mathjax-0.4.8.tgz",
- "integrity": "sha512-eFFYR6Qo9eZnS+3vUVIHd1lLasx6Upybu3tvdNJ119CUkVd3edtvDqI286RJuApfyDM0uAzkqEgmSKCr4pT8NA==",
- "dev": true,
- "dependencies": {
- "@mdit/plugin-tex": "0.4.8",
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1",
- "mathjax-full": "^3.2.2",
- "upath": "^2.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-mathjax/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-stylize": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-stylize/-/plugin-stylize-0.4.8.tgz",
- "integrity": "sha512-Wjo3hEHGybu+2ubLaUY52g5SCk6ThFwHYQAYScB7NX39lbr1xefVKs5RYeyH3xCRMdK3S5+b1mlklrdSARQ1fg==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-stylize/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-sub": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-sub/-/plugin-sub-0.4.8.tgz",
- "integrity": "sha512-U/6FtGgakdk/JhybHGHykBampF5YMZFkS1DB9uht/3uycWT4ejGefZ1XT9r59liQ3Bh/9CTy0niRNvMwdolPOA==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-sub/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-sup": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-sup/-/plugin-sup-0.4.8.tgz",
- "integrity": "sha512-wv4n9PKoiXI2RFqUrqOSxcKl71mTNCzlNJNlb4WfF9OTIn1CXR298EeL6XnbgS6snLuraur15PgGqwWw6wP7AQ==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-sup/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-tab": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-tab/-/plugin-tab-0.4.8.tgz",
- "integrity": "sha512-/YUI4KQAtHUE6AkJUfIEIKjnK8LEAkcBMe2z8SYmzeEs9U0vHvQNawUd6ANHOXrpeqyPrgQnhWqGkF4yMqfAjg==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- }
- },
- "node_modules/@mdit/plugin-tab/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-tasklist": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-tasklist/-/plugin-tasklist-0.4.8.tgz",
- "integrity": "sha512-VAnCR4dnfqOpW1hPEAunJFVvV31eARnD23XPSK3JAQADUFtnileoR0OdXZATC4gTsuVnYh8V8d7rujjL1QvxQw==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-tasklist/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-tex": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-tex/-/plugin-tex-0.4.8.tgz",
- "integrity": "sha512-HgWb8l0Can+NsxFfLu358Xwj1plxXHXf2YkjxM316pUeVZhNhjPjoqIpR46ebCwWbWW+GmwT0YdeUvQrDgM3ig==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-tex/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@mdit/plugin-uml": {
- "version": "0.4.8",
- "resolved": "https://registry.npmmirror.com/@mdit/plugin-uml/-/plugin-uml-0.4.8.tgz",
- "integrity": "sha512-X414T54zh0i+n5MbPL0kzGwRzcCU0hlpe4wp74cr44RWrsvJ8+78ioOx7WJOM8rgGHRWIoEEp6BjB1WfI734Iw==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^12.2.3",
- "markdown-it": "^13.0.1"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@mdit/plugin-uml/node_modules/@types/markdown-it": {
- "version": "12.2.3",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-12.2.3.tgz",
- "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@stackblitz/sdk": {
- "version": "1.9.0",
- "resolved": "https://registry.npmmirror.com/@stackblitz/sdk/-/sdk-1.9.0.tgz",
- "integrity": "sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==",
- "dev": true
- },
- "node_modules/@surma/rollup-plugin-off-main-thread": {
- "version": "2.2.3",
- "resolved": "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
- "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==",
- "dev": true,
- "dependencies": {
- "ejs": "^3.1.6",
- "json5": "^2.2.0",
- "magic-string": "^0.25.0",
- "string.prototype.matchall": "^4.0.6"
- }
- },
- "node_modules/@surma/rollup-plugin-off-main-thread/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "dev": true,
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
- "node_modules/@types/d3-scale": {
- "version": "4.0.5",
- "resolved": "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-4.0.5.tgz",
- "integrity": "sha512-w/C++3W394MHzcLKO2kdsIn5KKNTOqeQVzyPSGPLzQbkPw/jpeaGtSRlakcKevGgGsjJxGsbqS0fPrVFDbHrDA==",
- "dev": true,
- "dependencies": {
- "@types/d3-time": "*"
- }
- },
- "node_modules/@types/d3-scale-chromatic": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
- "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==",
- "dev": true
- },
- "node_modules/@types/d3-time": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/@types/d3-time/-/d3-time-3.0.1.tgz",
- "integrity": "sha512-5j/AnefKAhCw4HpITmLDTPlf4vhi8o/dES+zbegfPb7LaGfNyqkLxBR6E+4yvTAgnJLmhe80EXFMzUs38fw4oA==",
- "dev": true
- },
- "node_modules/@types/debug": {
- "version": "4.1.9",
- "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.9.tgz",
- "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==",
- "dev": true,
- "dependencies": {
- "@types/ms": "*"
- }
- },
- "node_modules/@types/eslint": {
- "version": "8.44.3",
- "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.44.3.tgz",
- "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@types/estree": "*",
- "@types/json-schema": "*"
- }
- },
- "node_modules/@types/eslint-scope": {
- "version": "3.7.5",
- "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.5.tgz",
- "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@types/eslint": "*",
- "@types/estree": "*"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.2.tgz",
- "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==",
- "dev": true,
- "peer": true
- },
- "node_modules/@types/fs-extra": {
- "version": "11.0.2",
- "resolved": "https://registry.npmmirror.com/@types/fs-extra/-/fs-extra-11.0.2.tgz",
- "integrity": "sha512-c0hrgAOVYr21EX8J0jBMXGLMgJqVf/v6yxi0dLaJboW9aQPh16Id+z6w2Tx1hm+piJOLv8xPfVKZCLfjPw/IMQ==",
- "dev": true,
- "dependencies": {
- "@types/jsonfile": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/hash-sum": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/@types/hash-sum/-/hash-sum-1.0.0.tgz",
- "integrity": "sha512-FdLBT93h3kcZ586Aee66HPCVJ6qvxVjBlDWNmxSGSbCZe9hTsjRKdSsl4y1T+3zfujxo9auykQMnFsfyHWD7wg==",
- "dev": true
- },
- "node_modules/@types/js-yaml": {
- "version": "4.0.6",
- "resolved": "https://registry.npmmirror.com/@types/js-yaml/-/js-yaml-4.0.6.tgz",
- "integrity": "sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw==",
- "dev": true
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.13",
- "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.13.tgz",
- "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
- "dev": true,
- "peer": true
- },
- "node_modules/@types/jsonfile": {
- "version": "6.1.2",
- "resolved": "https://registry.npmmirror.com/@types/jsonfile/-/jsonfile-6.1.2.tgz",
- "integrity": "sha512-8t92P+oeW4d/CRQfJaSqEwXujrhH4OEeHRjGU3v1Q8mUS8GPF3yiX26sw4svv6faL2HfBtGTe2xWIoVgN3dy9w==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/katex": {
- "version": "0.16.3",
- "resolved": "https://registry.npmmirror.com/@types/katex/-/katex-0.16.3.tgz",
- "integrity": "sha512-CeVMX9EhVUW8MWnei05eIRks4D5Wscw/W9Byz1s3PA+yJvcdvq9SaDjiUKvRvEgjpdTyJMjQA43ae4KTwsvOPg==",
- "dev": true
- },
- "node_modules/@types/linkify-it": {
- "version": "3.0.3",
- "resolved": "https://registry.npmmirror.com/@types/linkify-it/-/linkify-it-3.0.3.tgz",
- "integrity": "sha512-pTjcqY9E4nOI55Wgpz7eiI8+LzdYnw3qxXCfHyBDdPbYvbyLgWLJGh8EdPvqawwMK1Uo1794AUkkR38Fr0g+2g==",
- "dev": true
- },
- "node_modules/@types/markdown-it": {
- "version": "13.0.2",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-13.0.2.tgz",
- "integrity": "sha512-Tla7hH9oeXHOlJyBFdoqV61xWE9FZf/y2g+gFVwQ2vE1/eBzjUno5JCd3Hdb5oATve5OF6xNjZ/4VIZhVVx+hA==",
- "dev": true,
- "dependencies": {
- "@types/linkify-it": "*",
- "@types/mdurl": "*"
- }
- },
- "node_modules/@types/markdown-it-emoji": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/@types/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
- "integrity": "sha512-2ln8Wjbcj/0oRi/6VnuMeWEHHuK8uapFttvcLmDIe1GKCsFBLOLBX+D+xhDa9oWOQV0IpvxwrSfKKssAqqroog==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "*"
- }
- },
- "node_modules/@types/mdast": {
- "version": "3.0.13",
- "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-3.0.13.tgz",
- "integrity": "sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2"
- }
- },
- "node_modules/@types/mdurl": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/@types/mdurl/-/mdurl-1.0.3.tgz",
- "integrity": "sha512-T5k6kTXak79gwmIOaDF2UUQXFbnBE0zBUzF20pz7wDYu0RQMzWg+Ml/Pz50214NsFHBITkoi5VtdjFZnJ2ijjA==",
- "dev": true
- },
- "node_modules/@types/ms": {
- "version": "0.7.32",
- "resolved": "https://registry.npmmirror.com/@types/ms/-/ms-0.7.32.tgz",
- "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "20.8.2",
- "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.8.2.tgz",
- "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
- "dev": true
- },
- "node_modules/@types/raphael": {
- "version": "2.3.5",
- "resolved": "https://registry.npmmirror.com/@types/raphael/-/raphael-2.3.5.tgz",
- "integrity": "sha512-JROUjEWzHMlPLWTvkUr6QJRAE9fxq1DrRyIUTOPyrLbYNwrAdPMS3mFc8Kk3Gq8HH7y6nFGMkMPW/NVA/zhJ1Q==",
- "dev": true
- },
- "node_modules/@types/resolve": {
- "version": "1.17.1",
- "resolved": "https://registry.npmmirror.com/@types/resolve/-/resolve-1.17.1.tgz",
- "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/sax": {
- "version": "1.2.5",
- "resolved": "https://registry.npmmirror.com/@types/sax/-/sax-1.2.5.tgz",
- "integrity": "sha512-9jWta97bBVC027/MShr3gLab8gPhKy4l6qpb+UJLF5pDm3501NvA7uvqVCW+REFtx00oTi6Cq9JzLwgq6evVgw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/trusted-types": {
- "version": "2.0.4",
- "resolved": "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.4.tgz",
- "integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==",
- "dev": true
- },
- "node_modules/@types/unist": {
- "version": "2.0.8",
- "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.8.tgz",
- "integrity": "sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==",
- "dev": true
- },
- "node_modules/@types/web-bluetooth": {
- "version": "0.0.17",
- "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
- "integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==",
- "dev": true
- },
- "node_modules/@vitejs/plugin-vue": {
- "version": "4.4.0",
- "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz",
- "integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==",
- "dev": true,
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "peerDependencies": {
- "vite": "^4.0.0",
- "vue": "^3.2.25"
- }
- },
- "node_modules/@vue/compiler-core": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
- "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.21.3",
- "@vue/shared": "3.3.4",
- "estree-walker": "^2.0.2",
- "source-map-js": "^1.0.2"
- }
- },
- "node_modules/@vue/compiler-dom": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz",
- "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==",
- "dev": true,
- "dependencies": {
- "@vue/compiler-core": "3.3.4",
- "@vue/shared": "3.3.4"
- }
- },
- "node_modules/@vue/compiler-sfc": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
- "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.20.15",
- "@vue/compiler-core": "3.3.4",
- "@vue/compiler-dom": "3.3.4",
- "@vue/compiler-ssr": "3.3.4",
- "@vue/reactivity-transform": "3.3.4",
- "@vue/shared": "3.3.4",
- "estree-walker": "^2.0.2",
- "magic-string": "^0.30.0",
- "postcss": "^8.1.10",
- "source-map-js": "^1.0.2"
- }
- },
- "node_modules/@vue/compiler-ssr": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz",
- "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==",
- "dev": true,
- "dependencies": {
- "@vue/compiler-dom": "3.3.4",
- "@vue/shared": "3.3.4"
- }
- },
- "node_modules/@vue/devtools-api": {
- "version": "6.5.0",
- "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
- "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==",
- "dev": true
- },
- "node_modules/@vue/reactivity": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.4.tgz",
- "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==",
- "dev": true,
- "dependencies": {
- "@vue/shared": "3.3.4"
- }
- },
- "node_modules/@vue/reactivity-transform": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz",
- "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.20.15",
- "@vue/compiler-core": "3.3.4",
- "@vue/shared": "3.3.4",
- "estree-walker": "^2.0.2",
- "magic-string": "^0.30.0"
- }
- },
- "node_modules/@vue/repl": {
- "version": "2.5.8",
- "resolved": "https://registry.npmmirror.com/@vue/repl/-/repl-2.5.8.tgz",
- "integrity": "sha512-IvOlNhka4VKDQZS9FIceFFWyPibzqAUHyjHOoe8cMZmeP7H3H7mfMqvzQ0l1wjMAqqeEcgpFhSzMWsTEL4XZeA==",
- "dev": true
- },
- "node_modules/@vue/runtime-core": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.4.tgz",
- "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==",
- "dev": true,
- "dependencies": {
- "@vue/reactivity": "3.3.4",
- "@vue/shared": "3.3.4"
- }
- },
- "node_modules/@vue/runtime-dom": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz",
- "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==",
- "dev": true,
- "dependencies": {
- "@vue/runtime-core": "3.3.4",
- "@vue/shared": "3.3.4",
- "csstype": "^3.1.1"
- }
- },
- "node_modules/@vue/server-renderer": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
- "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
- "dev": true,
- "dependencies": {
- "@vue/compiler-ssr": "3.3.4",
- "@vue/shared": "3.3.4"
- },
- "peerDependencies": {
- "vue": "3.3.4"
- }
- },
- "node_modules/@vue/shared": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.4.tgz",
- "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==",
- "dev": true
- },
- "node_modules/@vuepress/bundler-vite": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/bundler-vite/-/bundler-vite-2.0.0-beta.67.tgz",
- "integrity": "sha512-W6YXixxu2G+xPECPFvx4Tzv5fmpBYvApEYVw7qfSNf/5YZ6aeIfV0AMGJZvhk7R/KniofvBTGCjAMSK4fqKp8w==",
- "dev": true,
- "dependencies": {
- "@vitejs/plugin-vue": "^4.3.3",
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "autoprefixer": "^10.4.15",
- "connect-history-api-fallback": "^2.0.0",
- "postcss": "^8.4.28",
- "postcss-load-config": "^4.0.1",
- "rollup": "^3.28.1",
- "vite": "~4.4.9",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- }
- },
- "node_modules/@vuepress/cli": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/cli/-/cli-2.0.0-beta.67.tgz",
- "integrity": "sha512-OWd5JMq9pEHrz2MTTQV91EoG+7o18s1JWKP7GBfYQ2DRAu/Hf4rZPmluuibhFolTvnTDuTtXrfb6Wbx4iZ+M9Q==",
- "dev": true,
- "dependencies": {
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "cac": "^6.7.14",
- "chokidar": "^3.5.3",
- "envinfo": "^7.10.0",
- "esbuild": "~0.18.20"
- },
- "bin": {
- "vuepress-cli": "bin/vuepress.js"
- }
- },
- "node_modules/@vuepress/client": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/client/-/client-2.0.0-beta.67.tgz",
- "integrity": "sha512-xfXZXmZmMbCvQxUhNltuAZzpoiwM0x9ke+DdPPDBF0oGMNDlmtOlsD7NcH322vQE3ehYy5mXJttXuEmfoNOG6A==",
- "dev": true,
- "dependencies": {
- "@vue/devtools-api": "^6.5.0",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- }
- },
- "node_modules/@vuepress/core": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/core/-/core-2.0.0-beta.67.tgz",
- "integrity": "sha512-pbCm1x+zFKZqpJjS68sv3ziEQLMn0KM04Q6W249stcTUUBrKox2OPx+OcX/BrN6yH60OviXN8hD6MgCnFSWdZA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/markdown": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4"
- }
- },
- "node_modules/@vuepress/markdown": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/markdown/-/markdown-2.0.0-beta.67.tgz",
- "integrity": "sha512-dwciE7dbfDruLan+w9x/LUl5dLdBWB39QXznX/Hhv4oPp+Mm4as53J58gqjuRPi6N25DfRi3ODrzjG5Lduwnfw==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/plugin-component": "^0.12.1",
- "@mdit-vue/plugin-frontmatter": "^0.12.1",
- "@mdit-vue/plugin-headers": "^0.12.1",
- "@mdit-vue/plugin-sfc": "^0.12.1",
- "@mdit-vue/plugin-title": "^0.12.1",
- "@mdit-vue/plugin-toc": "^0.12.1",
- "@mdit-vue/shared": "^0.12.1",
- "@mdit-vue/types": "^0.12.0",
- "@types/markdown-it": "^13.0.1",
- "@types/markdown-it-emoji": "^2.0.2",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "markdown-it": "^13.0.1",
- "markdown-it-anchor": "^8.6.7",
- "markdown-it-emoji": "^2.0.2",
- "mdurl": "^1.0.1"
- }
- },
- "node_modules/@vuepress/plugin-active-header-links": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-active-header-links/-/plugin-active-header-links-2.0.0-beta.67.tgz",
- "integrity": "sha512-2AxtFnnvHn750x+dCFbCWgqxpS+zsNucw8vuATmyRiBAleEqfM1Wz+RuMSKBM38GxsI/7mnQgWOgqj4S90G+ZA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "ts-debounce": "^4.0.0",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- }
- },
- "node_modules/@vuepress/plugin-back-to-top": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-back-to-top/-/plugin-back-to-top-2.0.0-beta.67.tgz",
- "integrity": "sha512-ystolf429cvAfX4qw1o9sHfkB8+KdQ4rV8P4ILR5LERgTZprL+1FbQfcHgVjEF2p0UKu2QXJQNGx2LfWWVuYdw==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "ts-debounce": "^4.0.0",
- "vue": "^3.3.4"
- }
- },
- "node_modules/@vuepress/plugin-container": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-container/-/plugin-container-2.0.0-beta.67.tgz",
- "integrity": "sha512-NuxjNkyJ2bYsRpw3iAiok2aeKYzZQsEZ8A/i+4LYwrDXbj3HfjlDhfPYhN+BMQfbxE9LpXOG0APNcXVCNMu0hw==",
- "dev": true,
- "dependencies": {
- "@types/markdown-it": "^13.0.1",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/markdown": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "markdown-it": "^13.0.1",
- "markdown-it-container": "^3.0.0"
- }
- },
- "node_modules/@vuepress/plugin-external-link-icon": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-external-link-icon/-/plugin-external-link-icon-2.0.0-beta.67.tgz",
- "integrity": "sha512-JD0/Uvt1WQXiGoAA0pjpqQ7OINDUm1TSgWeIpfPq9tZJNfgjmqUoartMFUuqcvl4eMi4Alfx0dWkzSF9qHL7Pg==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/markdown": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4"
- }
- },
- "node_modules/@vuepress/plugin-git": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-git/-/plugin-git-2.0.0-beta.67.tgz",
- "integrity": "sha512-9JSGmEtDqBWEmszqEE7spBjWdbeZo0jeMi2ZQLT4KgQrYh5fU/DO8MgeJxGXXd9xvpz4aVAzQR+gqYpL6kO5Jw==",
- "dev": true,
- "dependencies": {
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "execa": "^8.0.1"
- }
- },
- "node_modules/@vuepress/plugin-medium-zoom": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-medium-zoom/-/plugin-medium-zoom-2.0.0-beta.67.tgz",
- "integrity": "sha512-KLXfzKKbAhLSaRdbkHlvpbpYtaqINYBJ9gB4Q7CQ5AUaA8uStLG6rX0RjyhKAONfIJWuFiVYCp38QSI++fa/tA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "medium-zoom": "^1.0.8",
- "vue": "^3.3.4"
- }
- },
- "node_modules/@vuepress/plugin-nprogress": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-nprogress/-/plugin-nprogress-2.0.0-beta.67.tgz",
- "integrity": "sha512-BlqALWsNCllrqhMgRGz+50ah984XCwp1wejNYGP0ENEGSo1SY2dUI4AatIWep4Zj+0s7gbBR0swZc49hkLpENg==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- }
- },
- "node_modules/@vuepress/plugin-palette": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-palette/-/plugin-palette-2.0.0-beta.67.tgz",
- "integrity": "sha512-Ea2nLx9yH4c70MUQpFXuRAD6OZNVdyVGppvNwyGswutqPkRu7km18ml4Jk767iGMAVfzmrlphd6VIUJBUJ81JQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "chokidar": "^3.5.3"
- }
- },
- "node_modules/@vuepress/plugin-prismjs": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-prismjs/-/plugin-prismjs-2.0.0-beta.67.tgz",
- "integrity": "sha512-IaTc/BHwdO/ydfcoGmqUsDI5G2rPsgffxDtHx4pogaBCF2A6X9O++hrR/YExOHwwyhaE/6c6kflJAefaHb+Arg==",
- "dev": true,
- "dependencies": {
- "@vuepress/core": "2.0.0-beta.67",
- "prismjs": "^1.29.0"
- }
- },
- "node_modules/@vuepress/plugin-theme-data": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/plugin-theme-data/-/plugin-theme-data-2.0.0-beta.67.tgz",
- "integrity": "sha512-emTj1fvYXM/+WWObmgR0STRwkcDEM9QLD9ZP/JK5hEdt9KQnl8qO9NIzVfP/acgqbxFJQVvsmMSruXXknN68FQ==",
- "dev": true,
- "dependencies": {
- "@vue/devtools-api": "^6.5.0",
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4"
- }
- },
- "node_modules/@vuepress/shared": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/shared/-/shared-2.0.0-beta.67.tgz",
- "integrity": "sha512-gm8/6oAnd0Jh8g9xB89S+g8XJxt30QmeXK79J2Nwcbgy88CZnYbZssU1noyxFt4cHDX8wpUf8V5I388/dfHfoQ==",
- "dev": true,
- "dependencies": {
- "@mdit-vue/types": "^0.12.0",
- "@vue/shared": "^3.3.4"
- }
- },
- "node_modules/@vuepress/theme-default": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/theme-default/-/theme-default-2.0.0-beta.67.tgz",
- "integrity": "sha512-t8wfKaf/WUAifcKTYfnpsUxTVF5C4LUSiX2DH+JTt0lB/bv4SKQstuZtLvLiV9C4q2ekjGpitaW85T4KDnshug==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/plugin-active-header-links": "2.0.0-beta.67",
- "@vuepress/plugin-back-to-top": "2.0.0-beta.67",
- "@vuepress/plugin-container": "2.0.0-beta.67",
- "@vuepress/plugin-external-link-icon": "2.0.0-beta.67",
- "@vuepress/plugin-git": "2.0.0-beta.67",
- "@vuepress/plugin-medium-zoom": "2.0.0-beta.67",
- "@vuepress/plugin-nprogress": "2.0.0-beta.67",
- "@vuepress/plugin-palette": "2.0.0-beta.67",
- "@vuepress/plugin-prismjs": "2.0.0-beta.67",
- "@vuepress/plugin-theme-data": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "sass": "^1.66.1",
- "sass-loader": "^13.3.2",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- },
- "peerDependencies": {
- "sass-loader": "^13.2.1"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- }
- }
- },
- "node_modules/@vuepress/utils": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/@vuepress/utils/-/utils-2.0.0-beta.67.tgz",
- "integrity": "sha512-wCK0uggm4gXroy7UkS1u8wDQmD4b0L6Gjqd/1PZTDhNlMLsrjBx7lqqoIKqarMdB2wmDLroPJcC9otvCz2oQug==",
- "dev": true,
- "dependencies": {
- "@types/debug": "^4.1.8",
- "@types/fs-extra": "^11.0.1",
- "@types/hash-sum": "^1.0.0",
- "@vuepress/shared": "2.0.0-beta.67",
- "debug": "^4.3.4",
- "fs-extra": "^11.1.1",
- "globby": "^13.2.2",
- "hash-sum": "^2.0.0",
- "ora": "^7.0.1",
- "picocolors": "^1.0.0",
- "upath": "^2.0.1"
- }
- },
- "node_modules/@vueuse/core": {
- "version": "10.4.1",
- "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.4.1.tgz",
- "integrity": "sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==",
- "dev": true,
- "dependencies": {
- "@types/web-bluetooth": "^0.0.17",
- "@vueuse/metadata": "10.4.1",
- "@vueuse/shared": "10.4.1",
- "vue-demi": ">=0.14.5"
- }
- },
- "node_modules/@vueuse/core/node_modules/vue-demi": {
- "version": "0.14.6",
- "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
- "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "vue-demi-fix": "bin/vue-demi-fix.js",
- "vue-demi-switch": "bin/vue-demi-switch.js"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "@vue/composition-api": "^1.0.0-rc.1",
- "vue": "^3.0.0-0 || ^2.6.0"
- },
- "peerDependenciesMeta": {
- "@vue/composition-api": {
- "optional": true
- }
- }
- },
- "node_modules/@vueuse/metadata": {
- "version": "10.4.1",
- "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-10.4.1.tgz",
- "integrity": "sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==",
- "dev": true
- },
- "node_modules/@vueuse/shared": {
- "version": "10.4.1",
- "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-10.4.1.tgz",
- "integrity": "sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==",
- "dev": true,
- "dependencies": {
- "vue-demi": ">=0.14.5"
- }
- },
- "node_modules/@vueuse/shared/node_modules/vue-demi": {
- "version": "0.14.6",
- "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz",
- "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "vue-demi-fix": "bin/vue-demi-fix.js",
- "vue-demi-switch": "bin/vue-demi-switch.js"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "@vue/composition-api": "^1.0.0-rc.1",
- "vue": "^3.0.0-0 || ^2.6.0"
- },
- "peerDependenciesMeta": {
- "@vue/composition-api": {
- "optional": true
- }
- }
- },
- "node_modules/@waline/client": {
- "version": "2.15.8",
- "resolved": "https://registry.npmmirror.com/@waline/client/-/client-2.15.8.tgz",
- "integrity": "sha512-EBL7RXJUJs742miTvOU0Vt8NEmeJ63EN5TtSsYZfzjUdvEtlv+JsBbS5uiz3C9v5qV7Hz+XDZdc8nc13mG9vNQ==",
- "dev": true,
- "dependencies": {
- "@vueuse/core": "^10.4.1",
- "autosize": "^6.0.1",
- "marked": "^4.3.0",
- "vue": "^3.3.4"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/@webassemblyjs/ast": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.11.6.tgz",
- "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/helper-numbers": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/floating-point-hex-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
- "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
- "dev": true,
- "peer": true
- },
- "node_modules/@webassemblyjs/helper-api-error": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
- "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
- "dev": true,
- "peer": true
- },
- "node_modules/@webassemblyjs/helper-buffer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
- "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
- "dev": true,
- "peer": true
- },
- "node_modules/@webassemblyjs/helper-numbers": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
- "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/floating-point-hex-parser": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
- "@xtuc/long": "4.2.2"
- }
- },
- "node_modules/@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
- "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
- "dev": true,
- "peer": true
- },
- "node_modules/@webassemblyjs/helper-wasm-section": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
- "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/ieee754": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
- "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@xtuc/ieee754": "^1.2.0"
- }
- },
- "node_modules/@webassemblyjs/leb128": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
- "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@xtuc/long": "4.2.2"
- }
- },
- "node_modules/@webassemblyjs/utf8": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
- "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
- "dev": true,
- "peer": true
- },
- "node_modules/@webassemblyjs/wasm-edit": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
- "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/helper-wasm-section": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-opt": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6",
- "@webassemblyjs/wast-printer": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/wasm-gen": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
- "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/wasm-opt": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
- "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-buffer": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.11.6",
- "@webassemblyjs/wasm-parser": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/wasm-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
- "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
- }
- },
- "node_modules/@webassemblyjs/wast-printer": {
- "version": "1.11.6",
- "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
- "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.11.6",
- "@xtuc/long": "4.2.2"
- }
- },
- "node_modules/@xtuc/ieee754": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
- "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
- "dev": true,
- "peer": true
- },
- "node_modules/@xtuc/long": {
- "version": "4.2.2",
- "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz",
- "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
- "dev": true,
- "peer": true
- },
- "node_modules/abortcontroller-polyfill": {
- "version": "1.7.5",
- "resolved": "https://registry.npmmirror.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz",
- "integrity": "sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ==",
- "dev": true
- },
- "node_modules/acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-import-assertions": {
- "version": "1.9.0",
- "resolved": "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
- "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
- "dev": true,
- "peer": true,
- "peerDependencies": {
- "acorn": "^8"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "node_modules/ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "peer": true,
- "peerDependencies": {
- "ajv": "^6.9.1"
- }
- },
- "node_modules/ajv/node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true,
- "peer": true
- },
- "node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "resolved": "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
- },
- "node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
- }
- },
- "node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
- "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-array-buffer": "^3.0.2",
- "is-shared-array-buffer": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/artalk": {
- "version": "2.6.3",
- "resolved": "https://registry.npmmirror.com/artalk/-/artalk-2.6.3.tgz",
- "integrity": "sha512-4VIwT+wZ+eU+CfnsBpUtP3a2G6G8etWityPZTrBxuUMNFFGQP6OTFYo/p6S6TwcevyQcjHMRJHfmKJ8vKDY4vQ==",
- "dev": true,
- "dependencies": {
- "abortcontroller-polyfill": "^1.7.5",
- "hanabi": "^0.4.0",
- "insane": "^2.6.2",
- "marked": "^7.0.4"
- }
- },
- "node_modules/artalk/node_modules/marked": {
- "version": "7.0.5",
- "resolved": "https://registry.npmmirror.com/marked/-/marked-7.0.5.tgz",
- "integrity": "sha512-lwNAFTfXgqpt/XvK17a/8wY9/q6fcSPZT1aP6QW0u74VwaJF/Z9KbRcX23sWE4tODM+AolJNcUtErTkgOeFP/Q==",
- "dev": true,
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 16"
- }
- },
- "node_modules/artplayer": {
- "version": "5.0.9",
- "resolved": "https://registry.npmmirror.com/artplayer/-/artplayer-5.0.9.tgz",
- "integrity": "sha512-IM/DShYdmKFEA9jl08LYbTK2Jfz9s7qIjEH0xWjnxvVArUKZZKcoqwr6i54U0c4grtc/Uvb4wtCd78kvtSVlgw==",
- "dev": true,
- "dependencies": {
- "option-validator": "^2.0.6"
- }
- },
- "node_modules/assignment": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/assignment/-/assignment-2.0.0.tgz",
- "integrity": "sha512-naMULXjtgCs9SVUEtyvJNt68aF18em7/W+dhbR59kbz9cXWPEvUkCun2tqlgqRPSqZaKPpqLc5ZnwL8jVmJRvw==",
- "dev": true
- },
- "node_modules/async": {
- "version": "3.2.4",
- "resolved": "https://registry.npmmirror.com/async/-/async-3.2.4.tgz",
- "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
- "dev": true
- },
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "dev": true,
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/autoprefixer": {
- "version": "10.4.16",
- "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.16.tgz",
- "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==",
- "dev": true,
- "dependencies": {
- "browserslist": "^4.21.10",
- "caniuse-lite": "^1.0.30001538",
- "fraction.js": "^4.3.6",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.0.0",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/autosize": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/autosize/-/autosize-6.0.1.tgz",
- "integrity": "sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==",
- "dev": true
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.4.5",
- "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz",
- "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.22.6",
- "@babel/helper-define-polyfill-provider": "^0.4.2",
- "semver": "^6.3.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.8.4",
- "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.4.tgz",
- "integrity": "sha512-9l//BZZsPR+5XjyJMPtZSK4jv0BsTO1zDac2GC6ygx9WLGlcsnRd1Co0B2zT5fF5Ic6BZy+9m3HNZ3QcOeDKfg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.2",
- "core-js-compat": "^3.32.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.5.2",
- "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz",
- "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.4.2"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/balloon-css": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/balloon-css/-/balloon-css-1.2.0.tgz",
- "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==",
- "dev": true
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "dev": true
- },
- "node_modules/bcp-47": {
- "version": "1.0.8",
- "resolved": "https://registry.npmmirror.com/bcp-47/-/bcp-47-1.0.8.tgz",
- "integrity": "sha512-Y9y1QNBBtYtv7hcmoX0tR+tUNSFZGZ6OL6vKPObq8BbOhkCoyayF6ogfLTgAli/KuAEbsYHYUNq2AQuY6IuLag==",
- "dev": true,
- "dependencies": {
- "is-alphabetical": "^1.0.0",
- "is-alphanumerical": "^1.0.0",
- "is-decimal": "^1.0.0"
- }
- },
- "node_modules/bcp-47-match": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/bcp-47-match/-/bcp-47-match-1.0.3.tgz",
- "integrity": "sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w==",
- "dev": true
- },
- "node_modules/bcp-47-normalize": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/bcp-47-normalize/-/bcp-47-normalize-1.1.1.tgz",
- "integrity": "sha512-jWZ1Jdu3cs0EZdfCkS0UE9Gg01PtxnChjEBySeB+Zo6nkqtFfnvtoQQgP1qU1Oo4qgJgxhTI6Sf9y/pZIhPs0A==",
- "dev": true,
- "dependencies": {
- "bcp-47": "^1.0.0",
- "bcp-47-match": "^1.0.0"
- }
- },
- "node_modules/bcrypt-ts": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/bcrypt-ts/-/bcrypt-ts-4.0.0.tgz",
- "integrity": "sha512-EsO/XpRoEr+3d63rEwytqYUs2yeQcTdQ5qonRHgcRBUSY5yZXCSbgL1seMUt61Gx9JuYZaPIccWuAWqqmGU/TQ==",
- "dev": true
- },
- "node_modules/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/bl": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/bl/-/bl-5.1.0.tgz",
- "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
- "dev": true,
- "dependencies": {
- "buffer": "^6.0.3",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "dev": true
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.22.1",
- "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.1.tgz",
- "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
- "dev": true,
- "dependencies": {
- "caniuse-lite": "^1.0.30001541",
- "electron-to-chromium": "^1.4.535",
- "node-releases": "^2.0.13",
- "update-browserslist-db": "^1.0.13"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmmirror.com/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "dev": true,
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true
- },
- "node_modules/builtin-modules": {
- "version": "3.3.0",
- "resolved": "https://registry.npmmirror.com/builtin-modules/-/builtin-modules-3.3.0.tgz",
- "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cac": {
- "version": "6.7.14",
- "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001543",
- "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz",
- "integrity": "sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==",
- "dev": true
- },
- "node_modules/chalk": {
- "version": "5.3.0",
- "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz",
- "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
- "dev": true,
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- }
- },
- "node_modules/character-entities": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz",
- "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
- "dev": true
- },
- "node_modules/chart.js": {
- "version": "4.4.0",
- "resolved": "https://registry.npmmirror.com/chart.js/-/chart.js-4.4.0.tgz",
- "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==",
- "dev": true,
- "dependencies": {
- "@kurkle/color": "^0.3.0"
- },
- "engines": {
- "pnpm": ">=7"
- }
- },
- "node_modules/cheerio": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmmirror.com/cheerio/-/cheerio-1.0.0-rc.12.tgz",
- "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
- "dev": true,
- "dependencies": {
- "cheerio-select": "^2.1.0",
- "dom-serializer": "^2.0.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "htmlparser2": "^8.0.1",
- "parse5": "^7.0.0",
- "parse5-htmlparser2-tree-adapter": "^7.0.0"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/cheerio-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz",
- "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "dev": true,
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-select": "^5.1.0",
- "css-what": "^6.1.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1"
- }
- },
- "node_modules/chokidar": {
- "version": "3.5.3",
- "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz",
- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "dev": true,
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.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"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chrome-trace-event": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
- "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=6.0"
- }
- },
- "node_modules/cli-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz",
- "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
- "dev": true,
- "dependencies": {
- "restore-cursor": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/cli-spinners": {
- "version": "2.9.1",
- "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.1.tgz",
- "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cliui": {
- "version": "6.0.0",
- "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
- "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
- "dev": true,
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/codem-isoboxer": {
- "version": "0.3.9",
- "resolved": "https://registry.npmmirror.com/codem-isoboxer/-/codem-isoboxer-0.3.9.tgz",
- "integrity": "sha512-4XOTqEzBWrGOZaMd+sTED2hLpzfBbiQCf1W6OBGkIHqk1D8uwy8WFLazVbdQwfDpQ+vf39lqTGPa9IhWW0roTA==",
- "dev": true
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "node_modules/commander": {
- "version": "8.3.0",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
- "dev": true,
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/comment-regex": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/comment-regex/-/comment-regex-1.0.1.tgz",
- "integrity": "sha512-IWlN//Yfby92tOIje7J18HkNmWRR7JESA/BK8W7wqY/akITpU5B0JQWnbTjCfdChSrDNb0DrdA9jfAxiiBXyiQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/common-tags": {
- "version": "1.8.2",
- "resolved": "https://registry.npmmirror.com/common-tags/-/common-tags-1.8.2.tgz",
- "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
- "dev": true,
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/connect-history-api-fallback": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
- "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
- "dev": true,
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true
- },
- "node_modules/core-js": {
- "version": "3.33.0",
- "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.33.0.tgz",
- "integrity": "sha512-HoZr92+ZjFEKar5HS6MC776gYslNOKHt75mEBKWKnPeFDpZ6nH5OeF3S6HFT1mUAUZKrzkez05VboaX8myjSuw==",
- "dev": true,
- "hasInstallScript": true
- },
- "node_modules/core-js-compat": {
- "version": "3.33.0",
- "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.33.0.tgz",
- "integrity": "sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw==",
- "dev": true,
- "dependencies": {
- "browserslist": "^4.22.1"
- }
- },
- "node_modules/cose-base": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/cose-base/-/cose-base-1.0.3.tgz",
- "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==",
- "dev": true,
- "dependencies": {
- "layout-base": "^1.0.0"
- }
- },
- "node_modules/create-codepen": {
- "version": "0.0.3",
- "resolved": "https://registry.npmmirror.com/create-codepen/-/create-codepen-0.0.3.tgz",
- "integrity": "sha512-Yr9qDyJEZ32V8rZn+R19zomU/0bjHixp11sB+IgnZ5bEb41XJ86iHT3IXTGdqHF2NVx6dsZ1R4DjpxXvA2/dXg==",
- "dev": true
- },
- "node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/crypto-random-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
- "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/css-select": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/css-select/-/css-select-5.1.0.tgz",
- "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "dev": true,
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
- }
- },
- "node_modules/css-what": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz",
- "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz",
- "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
- "dev": true
- },
- "node_modules/custom-event-polyfill": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz",
- "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==",
- "dev": true
- },
- "node_modules/cytoscape": {
- "version": "3.26.0",
- "resolved": "https://registry.npmmirror.com/cytoscape/-/cytoscape-3.26.0.tgz",
- "integrity": "sha512-IV+crL+KBcrCnVVUCZW+zRRRFUZQcrtdOPXki+o4CFUWLdAEYvuZLcBSJC9EBK++suamERKzeY7roq2hdovV3w==",
- "dev": true,
- "dependencies": {
- "heap": "^0.2.6",
- "lodash": "^4.17.21"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/cytoscape-cose-bilkent": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz",
- "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==",
- "dev": true,
- "dependencies": {
- "cose-base": "^1.0.0"
- },
- "peerDependencies": {
- "cytoscape": "^3.2.0"
- }
- },
- "node_modules/cytoscape-fcose": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz",
- "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==",
- "dev": true,
- "dependencies": {
- "cose-base": "^2.2.0"
- },
- "peerDependencies": {
- "cytoscape": "^3.2.0"
- }
- },
- "node_modules/cytoscape-fcose/node_modules/cose-base": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/cose-base/-/cose-base-2.2.0.tgz",
- "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==",
- "dev": true,
- "dependencies": {
- "layout-base": "^2.0.0"
- }
- },
- "node_modules/cytoscape-fcose/node_modules/layout-base": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz",
- "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==",
- "dev": true
- },
- "node_modules/d3": {
- "version": "7.8.5",
- "resolved": "https://registry.npmmirror.com/d3/-/d3-7.8.5.tgz",
- "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
- "dev": true,
- "dependencies": {
- "d3-array": "3",
- "d3-axis": "3",
- "d3-brush": "3",
- "d3-chord": "3",
- "d3-color": "3",
- "d3-contour": "4",
- "d3-delaunay": "6",
- "d3-dispatch": "3",
- "d3-drag": "3",
- "d3-dsv": "3",
- "d3-ease": "3",
- "d3-fetch": "3",
- "d3-force": "3",
- "d3-format": "3",
- "d3-geo": "3",
- "d3-hierarchy": "3",
- "d3-interpolate": "3",
- "d3-path": "3",
- "d3-polygon": "3",
- "d3-quadtree": "3",
- "d3-random": "3",
- "d3-scale": "4",
- "d3-scale-chromatic": "3",
- "d3-selection": "3",
- "d3-shape": "3",
- "d3-time": "3",
- "d3-time-format": "4",
- "d3-timer": "3",
- "d3-transition": "3",
- "d3-zoom": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-array": {
- "version": "3.2.4",
- "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-3.2.4.tgz",
- "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
- "dev": true,
- "dependencies": {
- "internmap": "1 - 2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-axis": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-axis/-/d3-axis-3.0.0.tgz",
- "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-brush": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-brush/-/d3-brush-3.0.0.tgz",
- "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
- "dev": true,
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "3",
- "d3-transition": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-chord": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-chord/-/d3-chord-3.0.1.tgz",
- "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
- "dev": true,
- "dependencies": {
- "d3-path": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-color": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz",
- "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-contour": {
- "version": "4.0.2",
- "resolved": "https://registry.npmmirror.com/d3-contour/-/d3-contour-4.0.2.tgz",
- "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
- "dev": true,
- "dependencies": {
- "d3-array": "^3.2.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-delaunay": {
- "version": "6.0.4",
- "resolved": "https://registry.npmmirror.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
- "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
- "dev": true,
- "dependencies": {
- "delaunator": "5"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dispatch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
- "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-drag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz",
- "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
- "dev": true,
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-selection": "3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-dsv/-/d3-dsv-3.0.1.tgz",
- "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
- "dev": true,
- "dependencies": {
- "commander": "7",
- "iconv-lite": "0.6",
- "rw": "1"
- },
- "bin": {
- "csv2json": "bin/dsv2json.js",
- "csv2tsv": "bin/dsv2dsv.js",
- "dsv2dsv": "bin/dsv2dsv.js",
- "dsv2json": "bin/dsv2json.js",
- "json2csv": "bin/json2dsv.js",
- "json2dsv": "bin/json2dsv.js",
- "json2tsv": "bin/json2dsv.js",
- "tsv2csv": "bin/dsv2dsv.js",
- "tsv2json": "bin/dsv2json.js"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-dsv/node_modules/commander": {
- "version": "7.2.0",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-7.2.0.tgz",
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
- "dev": true,
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/d3-ease": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz",
- "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-fetch": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-fetch/-/d3-fetch-3.0.1.tgz",
- "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
- "dev": true,
- "dependencies": {
- "d3-dsv": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-force": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-force/-/d3-force-3.0.0.tgz",
- "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
- "dev": true,
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-quadtree": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-format": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/d3-format/-/d3-format-3.1.0.tgz",
- "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-geo": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/d3-geo/-/d3-geo-3.1.0.tgz",
- "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
- "dev": true,
- "dependencies": {
- "d3-array": "2.5.0 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-hierarchy": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
- "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-interpolate": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
- "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
- "dev": true,
- "dependencies": {
- "d3-color": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-3.1.0.tgz",
- "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-polygon": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-polygon/-/d3-polygon-3.0.1.tgz",
- "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-quadtree": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
- "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-random": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-random/-/d3-random-3.0.1.tgz",
- "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-sankey": {
- "version": "0.12.3",
- "resolved": "https://registry.npmmirror.com/d3-sankey/-/d3-sankey-0.12.3.tgz",
- "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==",
- "dev": true,
- "dependencies": {
- "d3-array": "1 - 2",
- "d3-shape": "^1.2.0"
- }
- },
- "node_modules/d3-sankey/node_modules/d3-array": {
- "version": "2.12.1",
- "resolved": "https://registry.npmmirror.com/d3-array/-/d3-array-2.12.1.tgz",
- "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==",
- "dev": true,
- "dependencies": {
- "internmap": "^1.0.0"
- }
- },
- "node_modules/d3-sankey/node_modules/d3-path": {
- "version": "1.0.9",
- "resolved": "https://registry.npmmirror.com/d3-path/-/d3-path-1.0.9.tgz",
- "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==",
- "dev": true
- },
- "node_modules/d3-sankey/node_modules/d3-shape": {
- "version": "1.3.7",
- "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-1.3.7.tgz",
- "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
- "dev": true,
- "dependencies": {
- "d3-path": "1"
- }
- },
- "node_modules/d3-sankey/node_modules/internmap": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/internmap/-/internmap-1.0.1.tgz",
- "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==",
- "dev": true
- },
- "node_modules/d3-scale": {
- "version": "4.0.2",
- "resolved": "https://registry.npmmirror.com/d3-scale/-/d3-scale-4.0.2.tgz",
- "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
- "dev": true,
- "dependencies": {
- "d3-array": "2.10.0 - 3",
- "d3-format": "1 - 3",
- "d3-interpolate": "1.2.0 - 3",
- "d3-time": "2.1.1 - 3",
- "d3-time-format": "2 - 4"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-scale-chromatic": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
- "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==",
- "dev": true,
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-interpolate": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-selection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz",
- "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-shape": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/d3-shape/-/d3-shape-3.2.0.tgz",
- "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
- "dev": true,
- "dependencies": {
- "d3-path": "^3.1.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/d3-time/-/d3-time-3.1.0.tgz",
- "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
- "dev": true,
- "dependencies": {
- "d3-array": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-time-format": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/d3-time-format/-/d3-time-format-4.1.0.tgz",
- "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
- "dev": true,
- "dependencies": {
- "d3-time": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-timer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz",
- "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/d3-transition": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz",
- "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
- "dev": true,
- "dependencies": {
- "d3-color": "1 - 3",
- "d3-dispatch": "1 - 3",
- "d3-ease": "1 - 3",
- "d3-interpolate": "1 - 3",
- "d3-timer": "1 - 3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "d3-selection": "2 - 3"
- }
- },
- "node_modules/d3-zoom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz",
- "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
- "dev": true,
- "dependencies": {
- "d3-dispatch": "1 - 3",
- "d3-drag": "2 - 3",
- "d3-interpolate": "1 - 3",
- "d3-selection": "2 - 3",
- "d3-transition": "2 - 3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/dagre-d3-es": {
- "version": "7.0.10",
- "resolved": "https://registry.npmmirror.com/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz",
- "integrity": "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==",
- "dev": true,
- "dependencies": {
- "d3": "^7.8.2",
- "lodash-es": "^4.17.21"
- }
- },
- "node_modules/dashjs": {
- "version": "4.7.2",
- "resolved": "https://registry.npmmirror.com/dashjs/-/dashjs-4.7.2.tgz",
- "integrity": "sha512-DSoSEK3Mvbw+u8Sf6xQW0f86dnC7Vn9CIk5oXeHr4zsJ6TiJK81/q3nNsGm2C9q9y9S0du+aR+AkKM04Bdt5BQ==",
- "dev": true,
- "dependencies": {
- "bcp-47-match": "^1.0.3",
- "bcp-47-normalize": "^1.1.1",
- "codem-isoboxer": "0.3.9",
- "es6-promise": "^4.2.8",
- "fast-deep-equal": "2.0.1",
- "html-entities": "^1.2.1",
- "imsc": "^1.1.3",
- "localforage": "^1.7.1",
- "path-browserify": "^1.0.1",
- "ua-parser-js": "^1.0.2"
- }
- },
- "node_modules/dayjs": {
- "version": "1.11.10",
- "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz",
- "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==",
- "dev": true
- },
- "node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "dependencies": {
- "ms": "2.1.2"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/decode-named-character-reference": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz",
- "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==",
- "dev": true,
- "dependencies": {
- "character-entities": "^2.0.0"
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.0.tgz",
- "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/delaunator": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/delaunator/-/delaunator-5.0.0.tgz",
- "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
- "dev": true,
- "dependencies": {
- "robust-predicates": "^3.0.0"
- }
- },
- "node_modules/dequal": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/diff": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/diff/-/diff-5.1.0.tgz",
- "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
- "dev": true,
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/dijkstrajs": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
- "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
- "dev": true
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "dev": true,
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
- }
- },
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "dev": true
- },
- "node_modules/domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "dev": true,
- "dependencies": {
- "domelementtype": "^2.3.0"
- },
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/dompurify": {
- "version": "3.0.6",
- "resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.0.6.tgz",
- "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==",
- "dev": true
- },
- "node_modules/domutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/domutils/-/domutils-3.1.0.tgz",
- "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
- "dev": true,
- "dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3"
- }
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
- },
- "node_modules/echarts": {
- "version": "5.4.3",
- "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.3.tgz",
- "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==",
- "dev": true,
- "dependencies": {
- "tslib": "2.3.0",
- "zrender": "5.4.4"
- }
- },
- "node_modules/ejs": {
- "version": "3.1.9",
- "resolved": "https://registry.npmmirror.com/ejs/-/ejs-3.1.9.tgz",
- "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
- "dev": true,
- "dependencies": {
- "jake": "^10.8.5"
- },
- "bin": {
- "ejs": "bin/cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.4.540",
- "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.540.tgz",
- "integrity": "sha512-aoCqgU6r9+o9/S7wkcSbmPRFi7OWZWiXS9rtjEd+Ouyu/Xyw5RSq2XN8s5Qp8IaFOLiRrhQCphCIjAxgG3eCAg==",
- "dev": true
- },
- "node_modules/elkjs": {
- "version": "0.8.2",
- "resolved": "https://registry.npmmirror.com/elkjs/-/elkjs-0.8.2.tgz",
- "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==",
- "dev": true
- },
- "node_modules/emoji-regex": {
- "version": "10.2.1",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-10.2.1.tgz",
- "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==",
- "dev": true
- },
- "node_modules/encode-utf8": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz",
- "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==",
- "dev": true
- },
- "node_modules/enhanced-resolve": {
- "version": "5.15.0",
- "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
- "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "graceful-fs": "^4.2.4",
- "tapable": "^2.2.0"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "dev": true,
- "engines": {
- "node": ">=0.12"
- }
- },
- "node_modules/envinfo": {
- "version": "7.10.0",
- "resolved": "https://registry.npmmirror.com/envinfo/-/envinfo-7.10.0.tgz",
- "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==",
- "dev": true,
- "bin": {
- "envinfo": "dist/cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.22.2",
- "resolved": "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.22.2.tgz",
- "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "arraybuffer.prototype.slice": "^1.0.2",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.6",
- "get-intrinsic": "^1.2.1",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.12",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.12.3",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.1",
- "safe-array-concat": "^1.0.1",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.8",
- "string.prototype.trimend": "^1.0.7",
- "string.prototype.trimstart": "^1.0.7",
- "typed-array-buffer": "^1.0.0",
- "typed-array-byte-length": "^1.0.0",
- "typed-array-byte-offset": "^1.0.0",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.11"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-module-lexer": {
- "version": "1.3.1",
- "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.3.1.tgz",
- "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==",
- "dev": true,
- "peer": true
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
- "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3",
- "has": "^1.0.3",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es6-promise": {
- "version": "4.2.8",
- "resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
- "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
- "dev": true
- },
- "node_modules/esbuild": {
- "version": "0.18.20",
- "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.18.20.tgz",
- "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.18.20",
- "@esbuild/android-arm64": "0.18.20",
- "@esbuild/android-x64": "0.18.20",
- "@esbuild/darwin-arm64": "0.18.20",
- "@esbuild/darwin-x64": "0.18.20",
- "@esbuild/freebsd-arm64": "0.18.20",
- "@esbuild/freebsd-x64": "0.18.20",
- "@esbuild/linux-arm": "0.18.20",
- "@esbuild/linux-arm64": "0.18.20",
- "@esbuild/linux-ia32": "0.18.20",
- "@esbuild/linux-loong64": "0.18.20",
- "@esbuild/linux-mips64el": "0.18.20",
- "@esbuild/linux-ppc64": "0.18.20",
- "@esbuild/linux-riscv64": "0.18.20",
- "@esbuild/linux-s390x": "0.18.20",
- "@esbuild/linux-x64": "0.18.20",
- "@esbuild/netbsd-x64": "0.18.20",
- "@esbuild/openbsd-x64": "0.18.20",
- "@esbuild/sunos-x64": "0.18.20",
- "@esbuild/win32-arm64": "0.18.20",
- "@esbuild/win32-ia32": "0.18.20",
- "@esbuild/win32-x64": "0.18.20"
- }
- },
- "node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/esm": {
- "version": "3.2.25",
- "resolved": "https://registry.npmmirror.com/esm/-/esm-3.2.25.tgz",
- "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
- "dev": true,
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esrecurse/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estree-walker": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
- "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
- "dev": true
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eve-raphael": {
- "version": "0.5.0",
- "resolved": "https://registry.npmmirror.com/eve-raphael/-/eve-raphael-0.5.0.tgz",
- "integrity": "sha512-jrxnPsCGqng1UZuEp9DecX/AuSyAszATSjf4oEcRxvfxa1Oux4KkIPKBAAWWnpdwfARtr+Q0o9aPYWjsROD7ug==",
- "dev": true
- },
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=0.8.x"
- }
- },
- "node_modules/execa": {
- "version": "8.0.1",
- "resolved": "https://registry.npmmirror.com/execa/-/execa-8.0.1.tgz",
- "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
- "dev": true,
- "dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^8.0.1",
- "human-signals": "^5.0.0",
- "is-stream": "^3.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^5.1.0",
- "onetime": "^6.0.0",
- "signal-exit": "^4.1.0",
- "strip-final-newline": "^3.0.0"
- },
- "engines": {
- "node": ">=16.17"
- }
- },
- "node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
- "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.3.1",
- "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz",
- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
- "dev": true,
- "dependencies": {
- "@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"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fflate": {
- "version": "0.8.1",
- "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.8.1.tgz",
- "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==",
- "dev": true
- },
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
- "dev": true,
- "dependencies": {
- "minimatch": "^5.0.1"
- }
- },
- "node_modules/filelist/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/flowchart.ts": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/flowchart.ts/-/flowchart.ts-1.0.0.tgz",
- "integrity": "sha512-U8FN9kg/U1xPdQ5xW3e/hZBSX7y/07zGESCrJ2mjlT8CLuhzPXHXRJrJ+VyFW0DEJLdj4O7MvJImg3sXeRGt1A==",
- "dev": true,
- "dependencies": {
- "@types/raphael": "^2.3.3",
- "raphael": "^2.3.0",
- "tslib": "^2.5.2"
- }
- },
- "node_modules/flowchart.ts/node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
- "dev": true
- },
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
- "node_modules/fraction.js": {
- "version": "4.3.6",
- "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.6.tgz",
- "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/fs-extra": {
- "version": "11.1.1",
- "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.1.1.tgz",
- "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.6",
- "resolved": "https://registry.npmmirror.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
- "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "functions-have-names": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
- "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3"
- }
- },
- "node_modules/get-own-enumerable-property-symbols": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
- "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
- "dev": true
- },
- "node_modules/get-stream": {
- "version": "8.0.1",
- "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-8.0.1.tgz",
- "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
- "dev": true,
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/giscus": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/giscus/-/giscus-1.3.0.tgz",
- "integrity": "sha512-A3tVLgSmpnh2sX9uGjo9MbzmTTEJirSyFUPRvkipvy37y9rhxUYDoh9kO37QVrP7Sc7QuJ+gihB6apkO0yDyTw==",
- "dev": true,
- "dependencies": {
- "lit": "^2.7.5"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/glob-to-regexp": {
- "version": "0.4.1",
- "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
- "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
- "dev": true,
- "peer": true
- },
- "node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/globby": {
- "version": "13.2.2",
- "resolved": "https://registry.npmmirror.com/globby/-/globby-13.2.2.tgz",
- "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
- "dev": true,
- "dependencies": {
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.3.0",
- "ignore": "^5.2.4",
- "merge2": "^1.4.1",
- "slash": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true
- },
- "node_modules/gray-matter": {
- "version": "4.0.3",
- "resolved": "https://registry.npmmirror.com/gray-matter/-/gray-matter-4.0.3.tgz",
- "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==",
- "dev": true,
- "dependencies": {
- "js-yaml": "^3.13.1",
- "kind-of": "^6.0.2",
- "section-matter": "^1.0.0",
- "strip-bom-string": "^1.0.0"
- },
- "engines": {
- "node": ">=6.0"
- }
- },
- "node_modules/hanabi": {
- "version": "0.4.0",
- "resolved": "https://registry.npmmirror.com/hanabi/-/hanabi-0.4.0.tgz",
- "integrity": "sha512-ixJH94fwmmVzUSdxl7TMkVZJmsq4d2JKrxedpM5V1V+91iVHL0q6NnJi4xiDahK6Vo00xT17H8H6b4F6RVbsOg==",
- "dev": true,
- "dependencies": {
- "comment-regex": "^1.0.0"
- }
- },
- "node_modules/has": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/has/-/has-1.0.4.tgz",
- "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
- "dev": true,
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.1"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/hash-sum": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
- "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
- "dev": true
- },
- "node_modules/he": {
- "version": "0.5.0",
- "resolved": "https://registry.npmmirror.com/he/-/he-0.5.0.tgz",
- "integrity": "sha512-DoufbNNOFzwRPy8uecq+j+VCPQ+JyDelHTmSgygrA5TsR8Cbw4Qcir5sGtWiusB4BdT89nmlaVDhSJOqC/33vw==",
- "dev": true,
- "bin": {
- "he": "bin/he"
- }
- },
- "node_modules/heap": {
- "version": "0.2.7",
- "resolved": "https://registry.npmmirror.com/heap/-/heap-0.2.7.tgz",
- "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==",
- "dev": true
- },
- "node_modules/hls.js": {
- "version": "1.4.12",
- "resolved": "https://registry.npmmirror.com/hls.js/-/hls.js-1.4.12.tgz",
- "integrity": "sha512-1RBpx2VihibzE3WE9kGoVCtrhhDWTzydzElk/kyRbEOLnb1WIE+3ZabM/L8BqKFTCL3pUy4QzhXgD1Q6Igr1JA==",
- "dev": true
- },
- "node_modules/html-entities": {
- "version": "1.4.0",
- "resolved": "https://registry.npmmirror.com/html-entities/-/html-entities-1.4.0.tgz",
- "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==",
- "dev": true
- },
- "node_modules/htmlparser2": {
- "version": "8.0.2",
- "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-8.0.2.tgz",
- "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
- "dev": true,
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "entities": "^4.4.0"
- }
- },
- "node_modules/human-signals": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-5.0.0.tgz",
- "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
- "dev": true,
- "engines": {
- "node": ">=16.17.0"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "dev": true,
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/idb": {
- "version": "7.1.1",
- "resolved": "https://registry.npmmirror.com/idb/-/idb-7.1.1.tgz",
- "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
- "dev": true
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "dev": true
- },
- "node_modules/ignore": {
- "version": "5.2.4",
- "resolved": "https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz",
- "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/immediate": {
- "version": "3.0.6",
- "resolved": "https://registry.npmmirror.com/immediate/-/immediate-3.0.6.tgz",
- "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
- "dev": true
- },
- "node_modules/immutable": {
- "version": "4.3.4",
- "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.4.tgz",
- "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==",
- "dev": true
- },
- "node_modules/imsc": {
- "version": "1.1.3",
- "resolved": "https://registry.npmmirror.com/imsc/-/imsc-1.1.3.tgz",
- "integrity": "sha512-IY0hMkVTNoqoYwKEp5UvNNKp/A5jeJUOrIO7judgOyhHT+xC6PA4VBOMAOhdtAYbMRHx9DTgI8p6Z6jhYQPFDA==",
- "dev": true,
- "dependencies": {
- "sax": "1.2.1"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "node_modules/insane": {
- "version": "2.6.2",
- "resolved": "https://registry.npmmirror.com/insane/-/insane-2.6.2.tgz",
- "integrity": "sha512-BqEL1CJsjJi+/C/zKZxv31zs3r6zkLH5Nz1WMFb7UBX2KHY2yXDpbFTSEmNHzomBbGDysIfkTX55A0mQZ2CQiw==",
- "dev": true,
- "dependencies": {
- "assignment": "2.0.0",
- "he": "0.5.0"
- }
- },
- "node_modules/internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/internmap": {
- "version": "2.0.3",
- "resolved": "https://registry.npmmirror.com/internmap/-/internmap-2.0.3.tgz",
- "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/is-alphabetical": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz",
- "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==",
- "dev": true
- },
- "node_modules/is-alphanumerical": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz",
- "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==",
- "dev": true,
- "dependencies": {
- "is-alphabetical": "^1.0.0",
- "is-decimal": "^1.0.0"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
- }
- },
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- }
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmmirror.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.13.0",
- "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.0.tgz",
- "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-decimal": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/is-decimal/-/is-decimal-1.0.4.tgz",
- "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
- "dev": true
- },
- "node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-interactive": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-2.0.0.tgz",
- "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/is-module": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/is-module/-/is-module-1.0.0.tgz",
- "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
- "dev": true
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/is-obj/-/is-obj-1.0.1.tgz",
- "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-regexp": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/is-regexp/-/is-regexp-1.0.0.tgz",
- "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- }
- },
- "node_modules/is-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-3.0.0.tgz",
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true,
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.12",
- "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.12.tgz",
- "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
- "dev": true,
- "dependencies": {
- "which-typed-array": "^1.1.11"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-unicode-supported": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
- "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/jake": {
- "version": "10.8.7",
- "resolved": "https://registry.npmmirror.com/jake/-/jake-10.8.7.tgz",
- "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==",
- "dev": true,
- "dependencies": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.4",
- "minimatch": "^3.1.2"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jake/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jake/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-worker": {
- "version": "27.5.1",
- "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz",
- "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@types/node": "*",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
- },
- "engines": {
- "node": ">= 10.13.0"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dev": true,
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true,
- "peer": true
- },
- "node_modules/json-schema": {
- "version": "0.4.0",
- "resolved": "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz",
- "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
- "dev": true
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "peer": true
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "dev": true,
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/jsonpointer": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.1.tgz",
- "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/katex": {
- "version": "0.16.9",
- "resolved": "https://registry.npmmirror.com/katex/-/katex-0.16.9.tgz",
- "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==",
- "dev": true,
- "dependencies": {
- "commander": "^8.3.0"
- },
- "bin": {
- "katex": "cli.js"
- }
- },
- "node_modules/khroma": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/khroma/-/khroma-2.0.0.tgz",
- "integrity": "sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==",
- "dev": true
- },
- "node_modules/kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/kleur": {
- "version": "4.1.5",
- "resolved": "https://registry.npmmirror.com/kleur/-/kleur-4.1.5.tgz",
- "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/layout-base": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/layout-base/-/layout-base-1.0.2.tgz",
- "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==",
- "dev": true
- },
- "node_modules/leven": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/lie": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/lie/-/lie-3.1.1.tgz",
- "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
- "dev": true,
- "dependencies": {
- "immediate": "~3.0.5"
- }
- },
- "node_modules/lilconfig": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.1.0.tgz",
- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/linkify-it": {
- "version": "4.0.1",
- "resolved": "https://registry.npmmirror.com/linkify-it/-/linkify-it-4.0.1.tgz",
- "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
- "dev": true,
- "dependencies": {
- "uc.micro": "^1.0.1"
- }
- },
- "node_modules/lit": {
- "version": "2.8.0",
- "resolved": "https://registry.npmmirror.com/lit/-/lit-2.8.0.tgz",
- "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==",
- "dev": true,
- "dependencies": {
- "@lit/reactive-element": "^1.6.0",
- "lit-element": "^3.3.0",
- "lit-html": "^2.8.0"
- }
- },
- "node_modules/lit-element": {
- "version": "3.3.3",
- "resolved": "https://registry.npmmirror.com/lit-element/-/lit-element-3.3.3.tgz",
- "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
- "dev": true,
- "dependencies": {
- "@lit-labs/ssr-dom-shim": "^1.1.0",
- "@lit/reactive-element": "^1.3.0",
- "lit-html": "^2.8.0"
- }
- },
- "node_modules/lit-html": {
- "version": "2.8.0",
- "resolved": "https://registry.npmmirror.com/lit-html/-/lit-html-2.8.0.tgz",
- "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
- "dev": true,
- "dependencies": {
- "@types/trusted-types": "^2.0.2"
- }
- },
- "node_modules/loader-runner": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz",
- "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=6.11.5"
- }
- },
- "node_modules/loadjs": {
- "version": "4.2.0",
- "resolved": "https://registry.npmmirror.com/loadjs/-/loadjs-4.2.0.tgz",
- "integrity": "sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA==",
- "dev": true
- },
- "node_modules/localforage": {
- "version": "1.10.0",
- "resolved": "https://registry.npmmirror.com/localforage/-/localforage-1.10.0.tgz",
- "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
- "dev": true,
- "dependencies": {
- "lie": "3.1.1"
- }
- },
- "node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "dev": true
- },
- "node_modules/lodash-es": {
- "version": "4.17.21",
- "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
- "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
- "dev": true
- },
- "node_modules/lodash.debounce": {
- "version": "4.0.8",
- "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
- "dev": true
- },
- "node_modules/lodash.sortby": {
- "version": "4.7.0",
- "resolved": "https://registry.npmmirror.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
- "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
- "dev": true
- },
- "node_modules/log-symbols": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-5.1.0.tgz",
- "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
- "dev": true,
- "dependencies": {
- "chalk": "^5.0.0",
- "is-unicode-supported": "^1.1.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/magic-string": {
- "version": "0.30.4",
- "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.4.tgz",
- "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==",
- "dev": true,
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/markdown-it": {
- "version": "13.0.2",
- "resolved": "https://registry.npmmirror.com/markdown-it/-/markdown-it-13.0.2.tgz",
- "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1",
- "entities": "~3.0.1",
- "linkify-it": "^4.0.1",
- "mdurl": "^1.0.1",
- "uc.micro": "^1.0.5"
- },
- "bin": {
- "markdown-it": "bin/markdown-it.js"
- }
- },
- "node_modules/markdown-it-anchor": {
- "version": "8.6.7",
- "resolved": "https://registry.npmmirror.com/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz",
- "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==",
- "dev": true,
- "peerDependencies": {
- "@types/markdown-it": "*",
- "markdown-it": "*"
- }
- },
- "node_modules/markdown-it-container": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/markdown-it-container/-/markdown-it-container-3.0.0.tgz",
- "integrity": "sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==",
- "dev": true
- },
- "node_modules/markdown-it-emoji": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
- "integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==",
- "dev": true
- },
- "node_modules/markdown-it/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/markdown-it/node_modules/entities": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz",
- "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
- "dev": true,
- "engines": {
- "node": ">=0.12"
- }
- },
- "node_modules/marked": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/marked/-/marked-4.3.0.tgz",
- "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==",
- "dev": true,
- "bin": {
- "marked": "bin/marked.js"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/mathjax-full": {
- "version": "3.2.2",
- "resolved": "https://registry.npmmirror.com/mathjax-full/-/mathjax-full-3.2.2.tgz",
- "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==",
- "dev": true,
- "dependencies": {
- "esm": "^3.2.25",
- "mhchemparser": "^4.1.0",
- "mj-context-menu": "^0.6.1",
- "speech-rule-engine": "^4.0.6"
- }
- },
- "node_modules/maverick.js": {
- "version": "0.37.0",
- "resolved": "https://registry.npmmirror.com/maverick.js/-/maverick.js-0.37.0.tgz",
- "integrity": "sha512-1Dk/9rienLiihlktVvH04ADC2UJTMflC1fOMVQCCaQAaz7hgzDI5i0p/arFbDM52hFFiIcq4RdXtYz47SgsLgw==",
- "dev": true,
- "dependencies": {
- "@maverick-js/signals": "^5.10.3",
- "type-fest": "^3.8.0"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/mdast-util-from-markdown": {
- "version": "1.3.1",
- "resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz",
- "integrity": "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0",
- "@types/unist": "^2.0.0",
- "decode-named-character-reference": "^1.0.0",
- "mdast-util-to-string": "^3.1.0",
- "micromark": "^3.0.0",
- "micromark-util-decode-numeric-character-reference": "^1.0.0",
- "micromark-util-decode-string": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "unist-util-stringify-position": "^3.0.0",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/mdast-util-to-string": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz",
- "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==",
- "dev": true,
- "dependencies": {
- "@types/mdast": "^3.0.0"
- }
- },
- "node_modules/mdurl": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/mdurl/-/mdurl-1.0.1.tgz",
- "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
- "dev": true
- },
- "node_modules/media-captions": {
- "version": "0.0.18",
- "resolved": "https://registry.npmmirror.com/media-captions/-/media-captions-0.0.18.tgz",
- "integrity": "sha512-JW18P6FuHdyLSGwC4TQ0kF3WdNj/+wMw2cKOb8BnmY6vSJGtnwJ+vkYj+IjHOV34j3XMc70HDeB/QYKR7E7fuQ==",
- "dev": true,
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/medium-zoom": {
- "version": "1.0.8",
- "resolved": "https://registry.npmmirror.com/medium-zoom/-/medium-zoom-1.0.8.tgz",
- "integrity": "sha512-CjFVuFq/IfrdqesAXfg+hzlDKu6A2n80ZIq0Kl9kWjoHh9j1N9Uvk5X0/MmN0hOfm5F9YBswlClhcwnmtwz7gA==",
- "dev": true
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/mermaid": {
- "version": "10.4.0",
- "resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-10.4.0.tgz",
- "integrity": "sha512-4QCQLp79lvz7UZxow5HUX7uWTPJOaQBVExduo91tliXC7v78i6kssZOPHxLL+Xs30KU72cpPn3g3imw/xm/gaw==",
- "dev": true,
- "dependencies": {
- "@braintree/sanitize-url": "^6.0.1",
- "@types/d3-scale": "^4.0.3",
- "@types/d3-scale-chromatic": "^3.0.0",
- "cytoscape": "^3.23.0",
- "cytoscape-cose-bilkent": "^4.1.0",
- "cytoscape-fcose": "^2.1.0",
- "d3": "^7.4.0",
- "d3-sankey": "^0.12.3",
- "dagre-d3-es": "7.0.10",
- "dayjs": "^1.11.7",
- "dompurify": "^3.0.5",
- "elkjs": "^0.8.2",
- "khroma": "^2.0.0",
- "lodash-es": "^4.17.21",
- "mdast-util-from-markdown": "^1.3.0",
- "non-layered-tidy-tree-layout": "^2.0.2",
- "stylis": "^4.1.3",
- "ts-dedent": "^2.2.0",
- "uuid": "^9.0.0",
- "web-worker": "^1.2.0"
- }
- },
- "node_modules/mhchemparser": {
- "version": "4.2.1",
- "resolved": "https://registry.npmmirror.com/mhchemparser/-/mhchemparser-4.2.1.tgz",
- "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==",
- "dev": true
- },
- "node_modules/micromark": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/micromark/-/micromark-3.2.0.tgz",
- "integrity": "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==",
- "dev": true,
- "dependencies": {
- "@types/debug": "^4.0.0",
- "debug": "^4.0.0",
- "decode-named-character-reference": "^1.0.0",
- "micromark-core-commonmark": "^1.0.1",
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-combine-extensions": "^1.0.0",
- "micromark-util-decode-numeric-character-reference": "^1.0.0",
- "micromark-util-encode": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-resolve-all": "^1.0.0",
- "micromark-util-sanitize-uri": "^1.0.0",
- "micromark-util-subtokenize": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.1",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/micromark-core-commonmark": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz",
- "integrity": "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==",
- "dev": true,
- "dependencies": {
- "decode-named-character-reference": "^1.0.0",
- "micromark-factory-destination": "^1.0.0",
- "micromark-factory-label": "^1.0.0",
- "micromark-factory-space": "^1.0.0",
- "micromark-factory-title": "^1.0.0",
- "micromark-factory-whitespace": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-classify-character": "^1.0.0",
- "micromark-util-html-tag-name": "^1.0.0",
- "micromark-util-normalize-identifier": "^1.0.0",
- "micromark-util-resolve-all": "^1.0.0",
- "micromark-util-subtokenize": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.1",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/micromark-factory-destination": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz",
- "integrity": "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==",
- "dev": true,
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-factory-label": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz",
- "integrity": "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==",
- "dev": true,
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/micromark-factory-space": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz",
- "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==",
- "dev": true,
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-factory-title": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz",
- "integrity": "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==",
- "dev": true,
- "dependencies": {
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-factory-whitespace": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz",
- "integrity": "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==",
- "dev": true,
- "dependencies": {
- "micromark-factory-space": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-util-character": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz",
- "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==",
- "dev": true,
- "dependencies": {
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-util-chunked": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz",
- "integrity": "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==",
- "dev": true,
- "dependencies": {
- "micromark-util-symbol": "^1.0.0"
- }
- },
- "node_modules/micromark-util-classify-character": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz",
- "integrity": "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==",
- "dev": true,
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-util-combine-extensions": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz",
- "integrity": "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==",
- "dev": true,
- "dependencies": {
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-util-decode-numeric-character-reference": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz",
- "integrity": "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==",
- "dev": true,
- "dependencies": {
- "micromark-util-symbol": "^1.0.0"
- }
- },
- "node_modules/micromark-util-decode-string": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz",
- "integrity": "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==",
- "dev": true,
- "dependencies": {
- "decode-named-character-reference": "^1.0.0",
- "micromark-util-character": "^1.0.0",
- "micromark-util-decode-numeric-character-reference": "^1.0.0",
- "micromark-util-symbol": "^1.0.0"
- }
- },
- "node_modules/micromark-util-encode": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz",
- "integrity": "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==",
- "dev": true
- },
- "node_modules/micromark-util-html-tag-name": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz",
- "integrity": "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==",
- "dev": true
- },
- "node_modules/micromark-util-normalize-identifier": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz",
- "integrity": "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==",
- "dev": true,
- "dependencies": {
- "micromark-util-symbol": "^1.0.0"
- }
- },
- "node_modules/micromark-util-resolve-all": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz",
- "integrity": "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==",
- "dev": true,
- "dependencies": {
- "micromark-util-types": "^1.0.0"
- }
- },
- "node_modules/micromark-util-sanitize-uri": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz",
- "integrity": "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==",
- "dev": true,
- "dependencies": {
- "micromark-util-character": "^1.0.0",
- "micromark-util-encode": "^1.0.0",
- "micromark-util-symbol": "^1.0.0"
- }
- },
- "node_modules/micromark-util-subtokenize": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz",
- "integrity": "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==",
- "dev": true,
- "dependencies": {
- "micromark-util-chunked": "^1.0.0",
- "micromark-util-symbol": "^1.0.0",
- "micromark-util-types": "^1.0.0",
- "uvu": "^0.5.0"
- }
- },
- "node_modules/micromark-util-symbol": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz",
- "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==",
- "dev": true
- },
- "node_modules/micromark-util-types": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz",
- "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==",
- "dev": true
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz",
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/mitt": {
- "version": "3.0.1",
- "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
- "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
- "dev": true
- },
- "node_modules/mj-context-menu": {
- "version": "0.6.1",
- "resolved": "https://registry.npmmirror.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
- "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==",
- "dev": true
- },
- "node_modules/mpegts.js": {
- "version": "1.7.3",
- "resolved": "https://registry.npmmirror.com/mpegts.js/-/mpegts.js-1.7.3.tgz",
- "integrity": "sha512-kqZ1C1IsbAQN72cK8vMrzKeM7hwrwSBbFAwVAc7PPweOeoZxCANrc7fAVDKMfYUzxdNkMTnec9tVmlxmKZB0TQ==",
- "dev": true,
- "dependencies": {
- "es6-promise": "^4.2.5",
- "webworkify-webpack": "^2.1.5"
- }
- },
- "node_modules/mri": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/mri/-/mri-1.2.0.tgz",
- "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
- },
- "node_modules/node-releases": {
- "version": "2.0.13",
- "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.13.tgz",
- "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
- "dev": true
- },
- "node_modules/non-layered-tidy-tree-layout": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz",
- "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==",
- "dev": true
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz",
- "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-path": {
- "version": "5.1.0",
- "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-5.1.0.tgz",
- "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
- "dev": true,
- "dependencies": {
- "path-key": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/npm-run-path/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "dev": true,
- "dependencies": {
- "boolbase": "^1.0.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "dev": true
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "6.0.0",
- "resolved": "https://registry.npmmirror.com/onetime/-/onetime-6.0.0.tgz",
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
- "dependencies": {
- "mimic-fn": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/option-validator": {
- "version": "2.0.6",
- "resolved": "https://registry.npmmirror.com/option-validator/-/option-validator-2.0.6.tgz",
- "integrity": "sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==",
- "dev": true,
- "dependencies": {
- "kind-of": "^6.0.3"
- }
- },
- "node_modules/ora": {
- "version": "7.0.1",
- "resolved": "https://registry.npmmirror.com/ora/-/ora-7.0.1.tgz",
- "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==",
- "dev": true,
- "dependencies": {
- "chalk": "^5.3.0",
- "cli-cursor": "^4.0.0",
- "cli-spinners": "^2.9.0",
- "is-interactive": "^2.0.0",
- "is-unicode-supported": "^1.3.0",
- "log-symbols": "^5.1.0",
- "stdin-discarder": "^0.1.0",
- "string-width": "^6.1.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dev": true,
- "dependencies": {
- "entities": "^4.4.0"
- }
- },
- "node_modules/parse5-htmlparser2-tree-adapter": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
- "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
- "dev": true,
- "dependencies": {
- "domhandler": "^5.0.2",
- "parse5": "^7.0.0"
- }
- },
- "node_modules/path-browserify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
- "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
- "dev": true
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/photoswipe": {
- "version": "5.4.2",
- "resolved": "https://registry.npmmirror.com/photoswipe/-/photoswipe-5.4.2.tgz",
- "integrity": "sha512-z5hr36nAIPOZbHJPbCJ/mQ3+ZlizttF9za5gKXKH/us1k4KNHaRbC63K1Px5sVVKUtGb/2+ixHpKqtwl0WAwvA==",
- "dev": true,
- "engines": {
- "node": ">= 0.12.0"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/plyr": {
- "version": "3.7.8",
- "resolved": "https://registry.npmmirror.com/plyr/-/plyr-3.7.8.tgz",
- "integrity": "sha512-yG/EHDobwbB/uP+4Bm6eUpJ93f8xxHjjk2dYcD1Oqpe1EcuQl5tzzw9Oq+uVAzd2lkM11qZfydSiyIpiB8pgdA==",
- "dev": true,
- "dependencies": {
- "core-js": "^3.26.1",
- "custom-event-polyfill": "^1.0.7",
- "loadjs": "^4.2.0",
- "rangetouch": "^2.0.1",
- "url-polyfill": "^1.1.12"
- }
- },
- "node_modules/pngjs": {
- "version": "5.0.0",
- "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
- "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
- "dev": true,
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.31",
- "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.31.tgz",
- "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
- "dev": true,
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-load-config": {
- "version": "4.0.1",
- "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
- "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
- "dev": true,
- "dependencies": {
- "lilconfig": "^2.0.5",
- "yaml": "^2.1.1"
- },
- "engines": {
- "node": ">= 14"
- },
- "peerDependencies": {
- "postcss": ">=8.0.9",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
- },
- "node_modules/pretty-bytes": {
- "version": "5.6.0",
- "resolved": "https://registry.npmmirror.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
- "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/prismjs": {
- "version": "1.29.0",
- "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.29.0.tgz",
- "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz",
- "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/qrcode": {
- "version": "1.5.3",
- "resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.3.tgz",
- "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
- "dev": true,
- "dependencies": {
- "dijkstrajs": "^1.0.1",
- "encode-utf8": "^1.0.3",
- "pngjs": "^5.0.0",
- "yargs": "^15.3.1"
- },
- "bin": {
- "qrcode": "bin/qrcode"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true
- },
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
- "dependencies": {
- "safe-buffer": "^5.1.0"
- }
- },
- "node_modules/rangetouch": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/rangetouch/-/rangetouch-2.0.1.tgz",
- "integrity": "sha512-sln+pNSc8NGaHoLzwNBssFSf/rSYkqeBXzX1AtJlkJiUaVSJSbRAWJk+4omsXkN+EJalzkZhWQ3th1m0FpR5xA==",
- "dev": true
- },
- "node_modules/raphael": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/raphael/-/raphael-2.3.0.tgz",
- "integrity": "sha512-w2yIenZAQnp257XUWGni4bLMVxpUpcIl7qgxEgDIXtmSypYtlNxfXWpOBxs7LBTps5sDwhRnrToJrMUrivqNTQ==",
- "dev": true,
- "dependencies": {
- "eve-raphael": "0.5.0"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "dev": true,
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/regenerate": {
- "version": "1.4.2",
- "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz",
- "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
- "dev": true
- },
- "node_modules/regenerate-unicode-properties": {
- "version": "10.1.1",
- "resolved": "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz",
- "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==",
- "dev": true,
- "dependencies": {
- "regenerate": "^1.4.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.14.0",
- "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
- "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
- "dev": true
- },
- "node_modules/regenerator-transform": {
- "version": "0.15.2",
- "resolved": "https://registry.npmmirror.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
- "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
- "dev": true,
- "dependencies": {
- "@babel/runtime": "^7.8.4"
- }
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.5.1",
- "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
- "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "set-function-name": "^2.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/regexpu-core": {
- "version": "5.3.2",
- "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-5.3.2.tgz",
- "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==",
- "dev": true,
- "dependencies": {
- "@babel/regjsgen": "^0.8.0",
- "regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.1.0",
- "regjsparser": "^0.9.1",
- "unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/register-service-worker": {
- "version": "1.7.2",
- "resolved": "https://registry.npmmirror.com/register-service-worker/-/register-service-worker-1.7.2.tgz",
- "integrity": "sha512-CiD3ZSanZqcMPRhtfct5K9f7i3OLCcBBWsJjLh1gW9RO/nS94sVzY59iS+fgYBOBqaBpf4EzfqUF3j9IG+xo8A==",
- "dev": true
- },
- "node_modules/regjsparser": {
- "version": "0.9.1",
- "resolved": "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.9.1.tgz",
- "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==",
- "dev": true,
- "dependencies": {
- "jsesc": "~0.5.0"
- },
- "bin": {
- "regjsparser": "bin/parser"
- }
- },
- "node_modules/regjsparser/node_modules/jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
- "dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
- "dev": true
- },
- "node_modules/resolve": {
- "version": "1.22.6",
- "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.6.tgz",
- "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- }
- },
- "node_modules/restore-cursor": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz",
- "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
- "dev": true,
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/restore-cursor/node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/restore-cursor/node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/restore-cursor/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/reveal.js": {
- "version": "4.6.1",
- "resolved": "https://registry.npmmirror.com/reveal.js/-/reveal.js-4.6.1.tgz",
- "integrity": "sha512-1CW0auaXNPmwmvQ7TwpszwVxMi2Xr5cTS3J3EBC/HHgbPF32Dn7aiu/LKWDOGjMbaDwKQiGmfqcoGQ74HUHCMw==",
- "dev": true,
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/robust-predicates": {
- "version": "3.0.2",
- "resolved": "https://registry.npmmirror.com/robust-predicates/-/robust-predicates-3.0.2.tgz",
- "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==",
- "dev": true
- },
- "node_modules/rollup": {
- "version": "3.29.4",
- "resolved": "https://registry.npmmirror.com/rollup/-/rollup-3.29.4.tgz",
- "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/rw": {
- "version": "1.3.3",
- "resolved": "https://registry.npmmirror.com/rw/-/rw-1.3.3.tgz",
- "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
- "dev": true
- },
- "node_modules/sade": {
- "version": "1.8.1",
- "resolved": "https://registry.npmmirror.com/sade/-/sade-1.8.1.tgz",
- "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
- "dev": true,
- "dependencies": {
- "mri": "^1.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/safe-array-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
- "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "isarray": "^2.0.5"
- },
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true
- },
- "node_modules/safe-regex-test": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
- },
- "node_modules/sass": {
- "version": "1.68.0",
- "resolved": "https://registry.npmmirror.com/sass/-/sass-1.68.0.tgz",
- "integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==",
- "dev": true,
- "dependencies": {
- "chokidar": ">=3.0.0 <4.0.0",
- "immutable": "^4.0.0",
- "source-map-js": ">=0.6.2 <2.0.0"
- },
- "bin": {
- "sass": "sass.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/sass-loader": {
- "version": "13.3.2",
- "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-13.3.2.tgz",
- "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==",
- "dev": true,
- "dependencies": {
- "neo-async": "^2.6.2"
- },
- "engines": {
- "node": ">= 14.15.0"
- },
- "peerDependencies": {
- "fibers": ">= 3.1.0",
- "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
- "sass": "^1.3.0",
- "sass-embedded": "*",
- "webpack": "^5.0.0"
- },
- "peerDependenciesMeta": {
- "fibers": {
- "optional": true
- },
- "node-sass": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- }
- }
- },
- "node_modules/sax": {
- "version": "1.2.1",
- "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.1.tgz",
- "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==",
- "dev": true
- },
- "node_modules/schema-utils": {
- "version": "3.3.0",
- "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz",
- "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@types/json-schema": "^7.0.8",
- "ajv": "^6.12.5",
- "ajv-keywords": "^3.5.2"
- },
- "engines": {
- "node": ">= 10.13.0"
- }
- },
- "node_modules/section-matter": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/section-matter/-/section-matter-1.0.0.tgz",
- "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==",
- "dev": true,
- "dependencies": {
- "extend-shallow": "^2.0.1",
- "kind-of": "^6.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/serialize-javascript": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
- "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "randombytes": "^2.1.0"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "dev": true
- },
- "node_modules/set-function-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/set-function-name/-/set-function-name-2.0.1.tgz",
- "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
- "dev": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- }
- },
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/sitemap": {
- "version": "7.1.1",
- "resolved": "https://registry.npmmirror.com/sitemap/-/sitemap-7.1.1.tgz",
- "integrity": "sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==",
- "dev": true,
- "dependencies": {
- "@types/node": "^17.0.5",
- "@types/sax": "^1.2.1",
- "arg": "^5.0.0",
- "sax": "^1.2.4"
- },
- "bin": {
- "sitemap": "dist/cli.js"
- },
- "engines": {
- "node": ">=12.0.0",
- "npm": ">=5.6.0"
- }
- },
- "node_modules/sitemap/node_modules/@types/node": {
- "version": "17.0.45",
- "resolved": "https://registry.npmmirror.com/@types/node/-/node-17.0.45.tgz",
- "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
- "dev": true
- },
- "node_modules/sitemap/node_modules/sax": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/sax/-/sax-1.3.0.tgz",
- "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==",
- "dev": true
- },
- "node_modules/slash": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/slash/-/slash-4.0.0.tgz",
- "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/sourcemap-codec": {
- "version": "1.4.8",
- "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
- "deprecated": "Please use @jridgewell/sourcemap-codec instead",
- "dev": true
- },
- "node_modules/speech-rule-engine": {
- "version": "4.0.7",
- "resolved": "https://registry.npmmirror.com/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz",
- "integrity": "sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g==",
- "dev": true,
- "dependencies": {
- "commander": "9.2.0",
- "wicked-good-xpath": "1.3.0",
- "xmldom-sre": "0.1.31"
- },
- "bin": {
- "sre": "bin/sre"
- }
- },
- "node_modules/speech-rule-engine/node_modules/commander": {
- "version": "9.2.0",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-9.2.0.tgz",
- "integrity": "sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==",
- "dev": true,
- "engines": {
- "node": "^12.20.0 || >=14"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "node_modules/stdin-discarder": {
- "version": "0.1.0",
- "resolved": "https://registry.npmmirror.com/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
- "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
- "dev": true,
- "dependencies": {
- "bl": "^5.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "dev": true,
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "6.1.0",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-6.1.0.tgz",
- "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==",
- "dev": true,
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^10.2.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/string.prototype.matchall": {
- "version": "4.0.10",
- "resolved": "https://registry.npmmirror.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
- "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "regexp.prototype.flags": "^1.5.0",
- "set-function-name": "^2.0.0",
- "side-channel": "^1.0.4"
- }
- },
- "node_modules/string.prototype.trim": {
- "version": "1.2.8",
- "resolved": "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
- "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
- "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.7",
- "resolved": "https://registry.npmmirror.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
- "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
- }
- },
- "node_modules/stringify-object": {
- "version": "3.3.0",
- "resolved": "https://registry.npmmirror.com/stringify-object/-/stringify-object-3.3.0.tgz",
- "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
- "dev": true,
- "dependencies": {
- "get-own-enumerable-property-symbols": "^3.0.0",
- "is-obj": "^1.0.1",
- "is-regexp": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/strip-bom-string": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz",
- "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/strip-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/strip-comments/-/strip-comments-2.0.1.tgz",
- "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "3.0.0",
- "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true,
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/striptags": {
- "version": "3.2.0",
- "resolved": "https://registry.npmmirror.com/striptags/-/striptags-3.2.0.tgz",
- "integrity": "sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==",
- "dev": true
- },
- "node_modules/stylis": {
- "version": "4.3.0",
- "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.3.0.tgz",
- "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==",
- "dev": true
- },
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/tapable": {
- "version": "2.2.1",
- "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz",
- "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/temp-dir": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/temp-dir/-/temp-dir-2.0.0.tgz",
- "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tempy": {
- "version": "0.6.0",
- "resolved": "https://registry.npmmirror.com/tempy/-/tempy-0.6.0.tgz",
- "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==",
- "dev": true,
- "dependencies": {
- "is-stream": "^2.0.0",
- "temp-dir": "^2.0.0",
- "type-fest": "^0.16.0",
- "unique-string": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tempy/node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tempy/node_modules/type-fest": {
- "version": "0.16.0",
- "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.16.0.tgz",
- "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/terser": {
- "version": "5.21.0",
- "resolved": "https://registry.npmmirror.com/terser/-/terser-5.21.0.tgz",
- "integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/source-map": "^0.3.3",
- "acorn": "^8.8.2",
- "commander": "^2.20.0",
- "source-map-support": "~0.5.20"
- },
- "bin": {
- "terser": "bin/terser"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/terser-webpack-plugin": {
- "version": "5.3.9",
- "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
- "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.17",
- "jest-worker": "^27.4.5",
- "schema-utils": "^3.1.1",
- "serialize-javascript": "^6.0.1",
- "terser": "^5.16.8"
- },
- "engines": {
- "node": ">= 10.13.0"
- },
- "peerDependencies": {
- "webpack": "^5.1.0"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- },
- "uglify-js": {
- "optional": true
- }
- }
- },
- "node_modules/terser/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/tr46": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/tr46/-/tr46-1.0.1.tgz",
- "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/ts-debounce": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/ts-debounce/-/ts-debounce-4.0.0.tgz",
- "integrity": "sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==",
- "dev": true
- },
- "node_modules/ts-dedent": {
- "version": "2.2.0",
- "resolved": "https://registry.npmmirror.com/ts-dedent/-/ts-dedent-2.2.0.tgz",
- "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
- "dev": true,
- "engines": {
- "node": ">=6.10"
- }
- },
- "node_modules/tslib": {
- "version": "2.3.0",
- "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
- "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
- "dev": true
- },
- "node_modules/twikoo": {
- "version": "1.6.21",
- "resolved": "https://registry.npmmirror.com/twikoo/-/twikoo-1.6.21.tgz",
- "integrity": "sha512-6CvXl1zQDomWlIit2eyiMVsp50EPNaykiq/wTaVrMGdyXnudwK3Ykc8QgFWJa50y/urjn9LpvYcDE2VekeydEQ==",
- "dev": true
- },
- "node_modules/type-fest": {
- "version": "3.13.1",
- "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-3.13.1.tgz",
- "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
- "dev": true,
- "engines": {
- "node": ">=14.16"
- }
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
- "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
- "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-byte-offset": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
- "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmmirror.com/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- }
- },
- "node_modules/ua-parser-js": {
- "version": "1.0.36",
- "resolved": "https://registry.npmmirror.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz",
- "integrity": "sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/uc.micro": {
- "version": "1.0.6",
- "resolved": "https://registry.npmmirror.com/uc.micro/-/uc.micro-1.0.6.tgz",
- "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
- "dev": true
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- }
- },
- "node_modules/unicode-canonical-property-names-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
- "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
- "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
- "dev": true,
- "dependencies": {
- "unicode-canonical-property-names-ecmascript": "^2.0.0",
- "unicode-property-aliases-ecmascript": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-value-ecmascript": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
- "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-property-aliases-ecmascript": {
- "version": "2.1.0",
- "resolved": "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
- "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unique-string": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/unique-string/-/unique-string-2.0.0.tgz",
- "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==",
- "dev": true,
- "dependencies": {
- "crypto-random-string": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/unist-util-stringify-position": {
- "version": "3.0.3",
- "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz",
- "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==",
- "dev": true,
- "dependencies": {
- "@types/unist": "^2.0.0"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz",
- "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
- "dev": true,
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/upath": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/upath/-/upath-2.0.1.tgz",
- "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==",
- "dev": true,
- "engines": {
- "node": ">=4",
- "yarn": "*"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.0.13",
- "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
- "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
- "dev": true,
- "dependencies": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/url-polyfill": {
- "version": "1.1.12",
- "resolved": "https://registry.npmmirror.com/url-polyfill/-/url-polyfill-1.1.12.tgz",
- "integrity": "sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==",
- "dev": true
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/uuid": {
- "version": "9.0.1",
- "resolved": "https://registry.npmmirror.com/uuid/-/uuid-9.0.1.tgz",
- "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
- "dev": true,
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/uvu": {
- "version": "0.5.6",
- "resolved": "https://registry.npmmirror.com/uvu/-/uvu-0.5.6.tgz",
- "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==",
- "dev": true,
- "dependencies": {
- "dequal": "^2.0.0",
- "diff": "^5.0.0",
- "kleur": "^4.0.3",
- "sade": "^1.7.3"
- },
- "bin": {
- "uvu": "bin.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/vidstack": {
- "version": "0.6.13",
- "resolved": "https://registry.npmmirror.com/vidstack/-/vidstack-0.6.13.tgz",
- "integrity": "sha512-g5wH6Hfc4EQqOI0Mm7qW4D1DWPZfQnlATLZuqpuVAKI8HOz4UGfd1v48MLK9cR+ZfPjVL4/iZLu7YOIdSX3L2g==",
- "dev": true,
- "dependencies": {
- "maverick.js": "0.37.0",
- "media-captions": "0.0.18",
- "type-fest": "^3.8.0"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/vite": {
- "version": "4.4.10",
- "resolved": "https://registry.npmmirror.com/vite/-/vite-4.4.10.tgz",
- "integrity": "sha512-TzIjiqx9BEXF8yzYdF2NTf1kFFbjMjUSV0LFZ3HyHoI3SGSPLnnFUKiIQtL3gl2AjHvMrprOvQ3amzaHgQlAxw==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vue": {
- "version": "3.3.4",
- "resolved": "https://registry.npmmirror.com/vue/-/vue-3.3.4.tgz",
- "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
- "dev": true,
- "dependencies": {
- "@vue/compiler-dom": "3.3.4",
- "@vue/compiler-sfc": "3.3.4",
- "@vue/runtime-dom": "3.3.4",
- "@vue/server-renderer": "3.3.4",
- "@vue/shared": "3.3.4"
- }
- },
- "node_modules/vue-router": {
- "version": "4.2.5",
- "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.5.tgz",
- "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==",
- "dev": true,
- "dependencies": {
- "@vue/devtools-api": "^6.5.0"
- },
- "peerDependencies": {
- "vue": "^3.2.0"
- }
- },
- "node_modules/vuepress": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/vuepress/-/vuepress-2.0.0-beta.67.tgz",
- "integrity": "sha512-931pKDOph20RKMLZAH5YYlMz+nfx9jcOQio1Gxk0pB7DwuSxAVFxPv2dbIUP4E/4uWOkLppRhLYcrOoxEbVYzA==",
- "dev": true,
- "dependencies": {
- "vuepress-vite": "2.0.0-beta.67"
- },
- "bin": {
- "vuepress": "bin/vuepress.js"
- },
- "engines": {
- "node": ">=16.19.0"
- }
- },
- "node_modules/vuepress-plugin-auto-catalog": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-auto-catalog/-/vuepress-plugin-auto-catalog-2.0.0-beta.237.tgz",
- "integrity": "sha512-hIi/6Uxb//LT7CfWNAT5Y++9puiG7xGw1h4Du3DncVU/99f7eWemNRDKK7jnXU+4Hl9zwszx5XQtvJxWiINUNA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-components": "2.0.0-beta.237",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-blog2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-blog2/-/vuepress-plugin-blog2-2.0.0-beta.237.tgz",
- "integrity": "sha512-DgAN39F+fhIZ95Snb9TNIUJUS+yJY9tVWzl3YeFljePEQlrCxtiaJzziXn/H9gzzlBXRwXZJ3okuy3eiSUEkpg==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "chokidar": "^3.5.3",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-comment2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-comment2/-/vuepress-plugin-comment2-2.0.0-beta.237.tgz",
- "integrity": "sha512-jfljV+k+mzibR8AbTKuJWmeHH7lSJAQJCVqBvifVVWLTKOrIBDv+NEFcXD49yIul69RnMi5W1XRbeqpYKRLztw==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@waline/client": "^2.15.7",
- "artalk": "^2.6.0",
- "giscus": "^1.3.0",
- "twikoo": "^1.6.18",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-components": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-components/-/vuepress-plugin-components-2.0.0-beta.237.tgz",
- "integrity": "sha512-EjXik6EJYi84+gXK6YodYKP9+f5DVCAOqKvPoXRS1T02V7lN9saJO8eShxinazYker/oIvRrGU+B4u70nwBR3A==",
- "dev": true,
- "dependencies": {
- "@stackblitz/sdk": "^1.9.0",
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "artplayer": "^5.0.9",
- "balloon-css": "^1.2.0",
- "create-codepen": "0.0.3",
- "dashjs": "^4.7.1",
- "hls.js": "^1.4.12",
- "mpegts.js": "^1.7.3",
- "plyr": "^3.7.8",
- "qrcode": "^1.5.3",
- "vidstack": "^0.6.13",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-reading-time2": "2.0.0-beta.237",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-copy-code2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-copy-code2/-/vuepress-plugin-copy-code2-2.0.0-beta.237.tgz",
- "integrity": "sha512-k8HhFrLLxFc81AURJQh4pXbAlRE4OdF5MflcCSCi4R104A+vNs2DvvkmQHtNTiLyXmrciS8oyS3LwUdRvilhxQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "balloon-css": "^1.2.0",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-copyright2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-copyright2/-/vuepress-plugin-copyright2-2.0.0-beta.237.tgz",
- "integrity": "sha512-42nGh5Kt/ePnWhBGFUCnrNhVzGKUAgZQjzaxz4iT9kfQnPMDFRjN96qycr6lNhF4Qr/MbHj8ZryWnWgyV2K/5g==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-feed2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-feed2/-/vuepress-plugin-feed2-2.0.0-beta.237.tgz",
- "integrity": "sha512-I/aIkwfrc4yqamjshIyXvEGc35U+UW0mX9nIvO+95eSV23B/fXiYhpeYbqHPNlPDINmyJr0W9qkge/NpV50kdQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "cheerio": "1.0.0-rc.12",
- "vuepress-shared": "2.0.0-beta.237",
- "xml-js": "^1.6.11"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-md-enhance": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-md-enhance/-/vuepress-plugin-md-enhance-2.0.0-beta.237.tgz",
- "integrity": "sha512-GPs4NRw/bhu2Y9dfnTcGKZp0mHGmrunqYh2Iz7ueo3XOF9pUtusLzPdtqM9xLOLWssnsToJaSFn4TQjUZs97HQ==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.22.15",
- "@mdit/plugin-align": "^0.4.8",
- "@mdit/plugin-attrs": "^0.4.8",
- "@mdit/plugin-container": "^0.4.8",
- "@mdit/plugin-figure": "^0.4.8",
- "@mdit/plugin-footnote": "^0.4.8",
- "@mdit/plugin-img-lazyload": "^0.4.8",
- "@mdit/plugin-img-mark": "^0.4.8",
- "@mdit/plugin-img-size": "^0.4.8",
- "@mdit/plugin-include": "^0.4.8",
- "@mdit/plugin-katex": "^0.4.8",
- "@mdit/plugin-mark": "^0.4.8",
- "@mdit/plugin-mathjax": "^0.4.8",
- "@mdit/plugin-stylize": "^0.4.8",
- "@mdit/plugin-sub": "^0.4.8",
- "@mdit/plugin-sup": "^0.4.8",
- "@mdit/plugin-tab": "^0.4.8",
- "@mdit/plugin-tasklist": "^0.4.8",
- "@mdit/plugin-tex": "^0.4.8",
- "@mdit/plugin-uml": "^0.4.8",
- "@types/js-yaml": "^4.0.5",
- "@types/markdown-it": "^13.0.1",
- "@vue/repl": "^2.5.8",
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "balloon-css": "^1.2.0",
- "chart.js": "^4.4.0",
- "echarts": "^5.4.3",
- "flowchart.ts": "^1.0.0",
- "js-yaml": "^4.1.0",
- "katex": "^0.16.8",
- "markdown-it": "^13.0.1",
- "mermaid": "10.4.0",
- "reveal.js": "^4.5.0",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-md-enhance/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/vuepress-plugin-md-enhance/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/vuepress-plugin-photo-swipe": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-photo-swipe/-/vuepress-plugin-photo-swipe-2.0.0-beta.237.tgz",
- "integrity": "sha512-s2gxl0LmY6nuyA2Nj5b8dLvtKQbNvzTFE8g7YwjvMvCql+YeI6t/ChnENXRUrwuHWegvQZu/U1EQ0DKJhU37hQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "photoswipe": "^5.3.9",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-pwa2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-pwa2/-/vuepress-plugin-pwa2-2.0.0-beta.237.tgz",
- "integrity": "sha512-7O1VUR1R/x/Q8bAcmvub97fTjtMbBd3/WcTNS3Q7DRnCd3eV3bEAkrcht9+EXteuVNnMuBh6EPMl5yg2zHTwnA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "mitt": "^3.0.1",
- "register-service-worker": "^1.7.2",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237",
- "workbox-build": "^7.0.0"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-reading-time2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-reading-time2/-/vuepress-plugin-reading-time2-2.0.0-beta.237.tgz",
- "integrity": "sha512-JTO1Eyhbhnfbhz8D6vqFfo0peRSt7M+ZnBx7ANf6T9AmTWYF0qO+HA1EuYTp35+YLsGyBMUl6vwmJAXjKSknag==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-rtl": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-rtl/-/vuepress-plugin-rtl-2.0.0-beta.237.tgz",
- "integrity": "sha512-aebNtuXZkp9UwlK6vEUtBep7RiKVBCArq6PWfqlt/AuWEKufNzrXRvVAGH+iLuDCQiVM5ZwBvN5/lofILY4iQg==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-sass-palette": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-sass-palette/-/vuepress-plugin-sass-palette-2.0.0-beta.237.tgz",
- "integrity": "sha512-Z0XpgRpYBp1ulL1zYk+H7XKnFU37HxTRGXFJLOkgEiTmVluQqYxH1pCrWDMvTkwoaEn+xOQytQgCW8S+5jrH0w==",
- "dev": true,
- "dependencies": {
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "chokidar": "^3.5.3",
- "sass": "^1.66.1",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-seo2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-seo2/-/vuepress-plugin-seo2-2.0.0-beta.237.tgz",
- "integrity": "sha512-MIZGkwTrIyIapNTROtqNK3WE/jK5AitfZKk1EC8XhEq0L2Py/aMaXjADwP3R68RqaORdk8PG1WqdYyKpuwVW6w==",
- "dev": true,
- "dependencies": {
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-plugin-sitemap2": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-plugin-sitemap2/-/vuepress-plugin-sitemap2-2.0.0-beta.237.tgz",
- "integrity": "sha512-+athoLPBBg9NR3br7WywqPQcsV2K6rkNf+brdssdXi3eYqoUKzatLfbmD8R3bFf53w320eZe1Pxnfijv2CEYuQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "sitemap": "^7.1.1",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-shared": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-shared/-/vuepress-shared-2.0.0-beta.237.tgz",
- "integrity": "sha512-R4lGkX0GD1yUyK0iDrWIZvJbuoGyi9Z41gPz3jFexJM4ojjirkuvLy6DuMwFCi80GKJlrfWq19Tpeo5z5foPBA==",
- "dev": true,
- "dependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "cheerio": "1.0.0-rc.12",
- "dayjs": "^1.11.9",
- "execa": "^8.0.1",
- "fflate": "^0.8.0",
- "gray-matter": "^4.0.3",
- "semver": "^7.5.4",
- "striptags": "^3.2.0",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-shared/node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/vuepress-shared/node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/vuepress-shared/node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "node_modules/vuepress-theme-hope": {
- "version": "2.0.0-beta.237",
- "resolved": "https://registry.npmmirror.com/vuepress-theme-hope/-/vuepress-theme-hope-2.0.0-beta.237.tgz",
- "integrity": "sha512-O4WGxHiYJFG60bQSr/4VbwGTboTE/QkY+/U1L8ePj69FuvdU6sSnmL55/Rz1eHPOM43qvkLxGOty/3UpXguDcQ==",
- "dev": true,
- "dependencies": {
- "@vuepress/cli": "2.0.0-beta.67",
- "@vuepress/client": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/plugin-active-header-links": "2.0.0-beta.67",
- "@vuepress/plugin-container": "2.0.0-beta.67",
- "@vuepress/plugin-external-link-icon": "2.0.0-beta.67",
- "@vuepress/plugin-git": "2.0.0-beta.67",
- "@vuepress/plugin-nprogress": "2.0.0-beta.67",
- "@vuepress/plugin-prismjs": "2.0.0-beta.67",
- "@vuepress/plugin-theme-data": "2.0.0-beta.67",
- "@vuepress/shared": "2.0.0-beta.67",
- "@vuepress/utils": "2.0.0-beta.67",
- "@vueuse/core": "^10.4.1",
- "balloon-css": "^1.2.0",
- "bcrypt-ts": "^4.0.0",
- "cheerio": "1.0.0-rc.12",
- "chokidar": "^3.5.3",
- "gray-matter": "^4.0.3",
- "vue": "^3.3.4",
- "vue-router": "^4.2.4",
- "vuepress-plugin-auto-catalog": "2.0.0-beta.237",
- "vuepress-plugin-blog2": "2.0.0-beta.237",
- "vuepress-plugin-comment2": "2.0.0-beta.237",
- "vuepress-plugin-components": "2.0.0-beta.237",
- "vuepress-plugin-copy-code2": "2.0.0-beta.237",
- "vuepress-plugin-copyright2": "2.0.0-beta.237",
- "vuepress-plugin-feed2": "2.0.0-beta.237",
- "vuepress-plugin-md-enhance": "2.0.0-beta.237",
- "vuepress-plugin-photo-swipe": "2.0.0-beta.237",
- "vuepress-plugin-pwa2": "2.0.0-beta.237",
- "vuepress-plugin-reading-time2": "2.0.0-beta.237",
- "vuepress-plugin-rtl": "2.0.0-beta.237",
- "vuepress-plugin-sass-palette": "2.0.0-beta.237",
- "vuepress-plugin-seo2": "2.0.0-beta.237",
- "vuepress-plugin-sitemap2": "2.0.0-beta.237",
- "vuepress-shared": "2.0.0-beta.237"
- },
- "engines": {
- "node": ">=16.19.0",
- "npm": ">=8",
- "pnpm": ">=7"
- },
- "peerDependencies": {
- "sass-loader": "^13.3.2",
- "vuepress": "2.0.0-beta.67",
- "vuepress-vite": "2.0.0-beta.67",
- "vuepress-webpack": "2.0.0-beta.67"
- },
- "peerDependenciesMeta": {
- "sass-loader": {
- "optional": true
- },
- "vuepress": {
- "optional": true
- },
- "vuepress-vite": {
- "optional": true
- },
- "vuepress-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/vuepress-vite": {
- "version": "2.0.0-beta.67",
- "resolved": "https://registry.npmmirror.com/vuepress-vite/-/vuepress-vite-2.0.0-beta.67.tgz",
- "integrity": "sha512-oaak2RPKBP0LeaDpDntlsQWLklCBf2vdeceXtPSLV2IzL/wtMHs5DQ/f7zXxCzvku3h/FIstmgoKq/vC0TvHkA==",
- "dev": true,
- "dependencies": {
- "@vuepress/bundler-vite": "2.0.0-beta.67",
- "@vuepress/cli": "2.0.0-beta.67",
- "@vuepress/core": "2.0.0-beta.67",
- "@vuepress/theme-default": "2.0.0-beta.67",
- "vue": "^3.3.4"
- },
- "bin": {
- "vuepress": "bin/vuepress.js",
- "vuepress-vite": "bin/vuepress.js"
- },
- "engines": {
- "node": ">=16.19.0"
- },
- "peerDependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "vue": "^3.3.4"
- }
- },
- "node_modules/watchpack": {
- "version": "2.4.0",
- "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.0.tgz",
- "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "glob-to-regexp": "^0.4.1",
- "graceful-fs": "^4.1.2"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/web-worker": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/web-worker/-/web-worker-1.2.0.tgz",
- "integrity": "sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==",
- "dev": true
- },
- "node_modules/webidl-conversions": {
- "version": "4.0.2",
- "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
- "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
- "dev": true
- },
- "node_modules/webpack": {
- "version": "5.88.2",
- "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.88.2.tgz",
- "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@types/eslint-scope": "^3.7.3",
- "@types/estree": "^1.0.0",
- "@webassemblyjs/ast": "^1.11.5",
- "@webassemblyjs/wasm-edit": "^1.11.5",
- "@webassemblyjs/wasm-parser": "^1.11.5",
- "acorn": "^8.7.1",
- "acorn-import-assertions": "^1.9.0",
- "browserslist": "^4.14.5",
- "chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.15.0",
- "es-module-lexer": "^1.2.1",
- "eslint-scope": "5.1.1",
- "events": "^3.2.0",
- "glob-to-regexp": "^0.4.1",
- "graceful-fs": "^4.2.9",
- "json-parse-even-better-errors": "^2.3.1",
- "loader-runner": "^4.2.0",
- "mime-types": "^2.1.27",
- "neo-async": "^2.6.2",
- "schema-utils": "^3.2.0",
- "tapable": "^2.1.1",
- "terser-webpack-plugin": "^5.3.7",
- "watchpack": "^2.4.0",
- "webpack-sources": "^3.2.3"
- },
- "bin": {
- "webpack": "bin/webpack.js"
- },
- "engines": {
- "node": ">=10.13.0"
- },
- "peerDependenciesMeta": {
- "webpack-cli": {
- "optional": true
- }
- }
- },
- "node_modules/webpack-sources": {
- "version": "3.2.3",
- "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz",
- "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
- "dev": true,
- "peer": true,
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/webworkify-webpack": {
- "version": "2.1.5",
- "resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
- "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==",
- "dev": true
- },
- "node_modules/whatwg-url": {
- "version": "7.1.0",
- "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-7.1.0.tgz",
- "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
- "dev": true,
- "dependencies": {
- "lodash.sortby": "^4.7.0",
- "tr46": "^1.0.1",
- "webidl-conversions": "^4.0.2"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- }
- },
- "node_modules/which-module": {
- "version": "2.0.1",
- "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
- "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
- "dev": true
- },
- "node_modules/which-typed-array": {
- "version": "1.1.11",
- "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.11.tgz",
- "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/wicked-good-xpath": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
- "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==",
- "dev": true
- },
- "node_modules/workbox-background-sync": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-background-sync/-/workbox-background-sync-7.0.0.tgz",
- "integrity": "sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==",
- "dev": true,
- "dependencies": {
- "idb": "^7.0.1",
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-broadcast-update": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-broadcast-update/-/workbox-broadcast-update-7.0.0.tgz",
- "integrity": "sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-build": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-build/-/workbox-build-7.0.0.tgz",
- "integrity": "sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==",
- "dev": true,
- "dependencies": {
- "@apideck/better-ajv-errors": "^0.3.1",
- "@babel/core": "^7.11.1",
- "@babel/preset-env": "^7.11.0",
- "@babel/runtime": "^7.11.2",
- "@rollup/plugin-babel": "^5.2.0",
- "@rollup/plugin-node-resolve": "^11.2.1",
- "@rollup/plugin-replace": "^2.4.1",
- "@surma/rollup-plugin-off-main-thread": "^2.2.3",
- "ajv": "^8.6.0",
- "common-tags": "^1.8.0",
- "fast-json-stable-stringify": "^2.1.0",
- "fs-extra": "^9.0.1",
- "glob": "^7.1.6",
- "lodash": "^4.17.20",
- "pretty-bytes": "^5.3.0",
- "rollup": "^2.43.1",
- "rollup-plugin-terser": "^7.0.0",
- "source-map": "^0.8.0-beta.0",
- "stringify-object": "^3.3.0",
- "strip-comments": "^2.0.1",
- "tempy": "^0.6.0",
- "upath": "^1.2.0",
- "workbox-background-sync": "7.0.0",
- "workbox-broadcast-update": "7.0.0",
- "workbox-cacheable-response": "7.0.0",
- "workbox-core": "7.0.0",
- "workbox-expiration": "7.0.0",
- "workbox-google-analytics": "7.0.0",
- "workbox-navigation-preload": "7.0.0",
- "workbox-precaching": "7.0.0",
- "workbox-range-requests": "7.0.0",
- "workbox-recipes": "7.0.0",
- "workbox-routing": "7.0.0",
- "workbox-strategies": "7.0.0",
- "workbox-streams": "7.0.0",
- "workbox-sw": "7.0.0",
- "workbox-window": "7.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": {
- "version": "0.3.6",
- "resolved": "https://registry.npmmirror.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz",
- "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==",
- "dev": true,
- "dependencies": {
- "json-schema": "^0.4.0",
- "jsonpointer": "^5.0.0",
- "leven": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "ajv": ">=8"
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/plugin-babel": {
- "version": "5.3.1",
- "resolved": "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
- "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-imports": "^7.10.4",
- "@rollup/pluginutils": "^3.1.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0",
- "@types/babel__core": "^7.1.9",
- "rollup": "^1.20.0||^2.0.0"
- },
- "peerDependenciesMeta": {
- "@types/babel__core": {
- "optional": true
- }
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/plugin-node-resolve": {
- "version": "11.2.1",
- "resolved": "https://registry.npmmirror.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz",
- "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==",
- "dev": true,
- "dependencies": {
- "@rollup/pluginutils": "^3.1.0",
- "@types/resolve": "1.17.1",
- "builtin-modules": "^3.1.0",
- "deepmerge": "^4.2.2",
- "is-module": "^1.0.0",
- "resolve": "^1.19.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/plugin-replace": {
- "version": "2.4.2",
- "resolved": "https://registry.npmmirror.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz",
- "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==",
- "dev": true,
- "dependencies": {
- "@rollup/pluginutils": "^3.1.0",
- "magic-string": "^0.25.7"
- },
- "peerDependencies": {
- "rollup": "^1.20.0 || ^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@rollup/pluginutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
- "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
- "dev": true,
- "dependencies": {
- "@types/estree": "0.0.39",
- "estree-walker": "^1.0.1",
- "picomatch": "^2.2.2"
- },
- "engines": {
- "node": ">= 8.0.0"
- },
- "peerDependencies": {
- "rollup": "^1.20.0||^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/@types/estree": {
- "version": "0.0.39",
- "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-0.0.39.tgz",
- "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
- "dev": true
- },
- "node_modules/workbox-build/node_modules/ajv": {
- "version": "8.12.0",
- "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz",
- "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2",
- "uri-js": "^4.2.2"
- }
- },
- "node_modules/workbox-build/node_modules/estree-walker": {
- "version": "1.0.1",
- "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-1.0.1.tgz",
- "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
- "dev": true
- },
- "node_modules/workbox-build/node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/workbox-build/node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
- "dev": true,
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/workbox-build/node_modules/jest-worker": {
- "version": "26.6.2",
- "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-26.6.2.tgz",
- "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "merge-stream": "^2.0.0",
- "supports-color": "^7.0.0"
- },
- "engines": {
- "node": ">= 10.13.0"
- }
- },
- "node_modules/workbox-build/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true
- },
- "node_modules/workbox-build/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "dev": true,
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
- "node_modules/workbox-build/node_modules/rollup": {
- "version": "2.79.1",
- "resolved": "https://registry.npmmirror.com/rollup/-/rollup-2.79.1.tgz",
- "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
- "dev": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/workbox-build/node_modules/rollup-plugin-terser": {
- "version": "7.0.2",
- "resolved": "https://registry.npmmirror.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
- "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
- "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "jest-worker": "^26.2.1",
- "serialize-javascript": "^4.0.0",
- "terser": "^5.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.0.0"
- }
- },
- "node_modules/workbox-build/node_modules/serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
- "dev": true,
- "dependencies": {
- "randombytes": "^2.1.0"
- }
- },
- "node_modules/workbox-build/node_modules/source-map": {
- "version": "0.8.0-beta.0",
- "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.8.0-beta.0.tgz",
- "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
- "dev": true,
- "dependencies": {
- "whatwg-url": "^7.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/workbox-build/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/workbox-build/node_modules/upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npmmirror.com/upath/-/upath-1.2.0.tgz",
- "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "dev": true,
- "engines": {
- "node": ">=4",
- "yarn": "*"
- }
- },
- "node_modules/workbox-cacheable-response": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-cacheable-response/-/workbox-cacheable-response-7.0.0.tgz",
- "integrity": "sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-core": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-core/-/workbox-core-7.0.0.tgz",
- "integrity": "sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==",
- "dev": true
- },
- "node_modules/workbox-expiration": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-expiration/-/workbox-expiration-7.0.0.tgz",
- "integrity": "sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==",
- "dev": true,
- "dependencies": {
- "idb": "^7.0.1",
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-google-analytics": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-google-analytics/-/workbox-google-analytics-7.0.0.tgz",
- "integrity": "sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==",
- "dev": true,
- "dependencies": {
- "workbox-background-sync": "7.0.0",
- "workbox-core": "7.0.0",
- "workbox-routing": "7.0.0",
- "workbox-strategies": "7.0.0"
- }
- },
- "node_modules/workbox-navigation-preload": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-navigation-preload/-/workbox-navigation-preload-7.0.0.tgz",
- "integrity": "sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-precaching": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-precaching/-/workbox-precaching-7.0.0.tgz",
- "integrity": "sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0",
- "workbox-routing": "7.0.0",
- "workbox-strategies": "7.0.0"
- }
- },
- "node_modules/workbox-range-requests": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-range-requests/-/workbox-range-requests-7.0.0.tgz",
- "integrity": "sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-recipes": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-recipes/-/workbox-recipes-7.0.0.tgz",
- "integrity": "sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==",
- "dev": true,
- "dependencies": {
- "workbox-cacheable-response": "7.0.0",
- "workbox-core": "7.0.0",
- "workbox-expiration": "7.0.0",
- "workbox-precaching": "7.0.0",
- "workbox-routing": "7.0.0",
- "workbox-strategies": "7.0.0"
- }
- },
- "node_modules/workbox-routing": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-routing/-/workbox-routing-7.0.0.tgz",
- "integrity": "sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-strategies": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-strategies/-/workbox-strategies-7.0.0.tgz",
- "integrity": "sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/workbox-streams": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-streams/-/workbox-streams-7.0.0.tgz",
- "integrity": "sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==",
- "dev": true,
- "dependencies": {
- "workbox-core": "7.0.0",
- "workbox-routing": "7.0.0"
- }
- },
- "node_modules/workbox-sw": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-sw/-/workbox-sw-7.0.0.tgz",
- "integrity": "sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==",
- "dev": true
- },
- "node_modules/workbox-window": {
- "version": "7.0.0",
- "resolved": "https://registry.npmmirror.com/workbox-window/-/workbox-window-7.0.0.tgz",
- "integrity": "sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==",
- "dev": true,
- "dependencies": {
- "@types/trusted-types": "^2.0.2",
- "workbox-core": "7.0.0"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/wrap-ansi/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/xml-js": {
- "version": "1.6.11",
- "resolved": "https://registry.npmmirror.com/xml-js/-/xml-js-1.6.11.tgz",
- "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
- "dev": true,
- "dependencies": {
- "sax": "^1.2.4"
- },
- "bin": {
- "xml-js": "bin/cli.js"
- }
- },
- "node_modules/xml-js/node_modules/sax": {
- "version": "1.3.0",
- "resolved": "https://registry.npmmirror.com/sax/-/sax-1.3.0.tgz",
- "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==",
- "dev": true
- },
- "node_modules/xmldom-sre": {
- "version": "0.1.31",
- "resolved": "https://registry.npmmirror.com/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
- "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==",
- "dev": true,
- "engines": {
- "node": ">=0.1"
- }
- },
- "node_modules/y18n": {
- "version": "4.0.3",
- "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
- "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
- "dev": true
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "node_modules/yaml": {
- "version": "2.3.2",
- "resolved": "https://registry.npmmirror.com/yaml/-/yaml-2.3.2.tgz",
- "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
- "dev": true,
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/yargs": {
- "version": "15.4.1",
- "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
- "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
- "dev": true,
- "dependencies": {
- "cliui": "^6.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^4.1.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^4.2.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^18.1.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs-parser": {
- "version": "18.1.3",
- "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
- "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
- "dev": true,
- "dependencies": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/yargs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/yargs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yargs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/zrender": {
- "version": "5.4.4",
- "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.4.tgz",
- "integrity": "sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==",
- "dev": true,
- "dependencies": {
- "tslib": "2.3.0"
- }
- }
- }
-}
diff --git a/package.json b/package.json
index a94793e..c4e7fdb 100644
--- a/package.json
+++ b/package.json
@@ -10,10 +10,14 @@
"docs:dev": "vuepress dev src",
"docs:update-package": "npx vp-update"
},
+ "packageManager": "pnpm@8.11.0",
"devDependencies": {
- "@vuepress/client": "2.0.0-beta.67",
- "vue": "^3.3.4",
- "vuepress": "2.0.0-beta.67",
- "vuepress-theme-hope": "2.0.0-beta.237"
+ "@vuepress/bundler-vite": "2.0.0-rc.0",
+ "@vuepress/client": "2.0.0-rc.0",
+ "@vuepress/utils": "2.0.0-rc.0",
+ "mermaid": "10.6.1",
+ "vue": "^3.3.10",
+ "vuepress": "2.0.0-rc.0",
+ "vuepress-theme-hope": "2.0.0-rc.2"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..883c62b
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,6549 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+devDependencies:
+ '@vuepress/bundler-vite':
+ specifier: 2.0.0-rc.0
+ version: 2.0.0-rc.0
+ '@vuepress/client':
+ specifier: 2.0.0-rc.0
+ version: 2.0.0-rc.0
+ '@vuepress/utils':
+ specifier: 2.0.0-rc.0
+ version: 2.0.0-rc.0
+ mermaid:
+ specifier: 10.6.1
+ version: 10.6.1
+ vue:
+ specifier: ^3.3.10
+ version: 3.3.10
+ vuepress:
+ specifier: 2.0.0-rc.0
+ version: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-theme-hope:
+ specifier: 2.0.0-rc.2
+ version: 2.0.0-rc.2(mermaid@10.6.1)(vuepress@2.0.0-rc.0)
+
+packages:
+
+ /@ampproject/remapping@2.2.1:
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@apideck/better-ajv-errors@0.3.6(ajv@8.12.0):
+ resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ ajv: '>=8'
+ dependencies:
+ ajv: 8.12.0
+ json-schema: 0.4.0
+ jsonpointer: 5.0.1
+ leven: 3.1.0
+ dev: true
+
+ /@babel/code-frame@7.23.5:
+ resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.23.4
+ chalk: 2.4.2
+ dev: true
+
+ /@babel/compat-data@7.23.5:
+ resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/core@7.23.5:
+ resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helpers': 7.23.5
+ '@babel/parser': 7.23.5
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.5
+ '@babel/types': 7.23.5
+ convert-source-map: 2.0.0
+ debug: 4.3.4
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/generator@7.23.5:
+ resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ jsesc: 2.5.2
+ dev: true
+
+ /@babel/helper-annotate-as-pure@7.22.5:
+ resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15:
+ resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-compilation-targets@7.22.15:
+ resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/helper-validator-option': 7.23.5
+ browserslist: 4.22.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-create-class-features-plugin@7.23.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.5):
+ resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ regexpu-core: 5.3.2
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-plugin-utils': 7.22.5
+ debug: 4.3.4
+ lodash.debounce: 4.0.8
+ resolve: 1.22.8
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/helper-environment-visitor@7.22.20:
+ resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-function-name@7.23.0:
+ resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-member-expression-to-functions@7.23.0:
+ resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-module-imports@7.22.15:
+ resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/helper-optimise-call-expression@7.22.5:
+ resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-plugin-utils@7.22.5:
+ resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.5):
+ resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-wrap-function': 7.22.20
+ dev: true
+
+ /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.5):
+ resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ dev: true
+
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-skip-transparent-expression-wrappers@7.22.5:
+ resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-split-export-declaration@7.22.6:
+ resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-string-parser@7.23.4:
+ resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.22.20:
+ resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-option@7.23.5:
+ resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-wrap-function@7.22.20:
+ resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-function-name': 7.23.0
+ '@babel/template': 7.22.15
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helpers@7.23.5:
+ resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.5
+ '@babel/types': 7.23.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/highlight@7.23.4:
+ resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.22.20
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser@7.23.5:
+ resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.13.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.5):
+ resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ dev: true
+
+ /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.5):
+ resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.5):
+ resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-async-generator-functions@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.5)
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.12.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-classes@7.23.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5)
+ '@babel/helper-split-export-declaration': 7.22.6
+ globals: 11.12.0
+ dev: true
+
+ /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/template': 7.22.15
+ dev: true
+
+ /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-for-of@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-literals@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-simple-access': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-new-target@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/core': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-object-super@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-parameters@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.23.5):
+ resolution: {integrity: sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ regenerator-transform: 0.15.2
+ dev: true
+
+ /@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/preset-env@7.23.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/core': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-validator-option': 7.23.5
+ '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.5)
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.5)
+ '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.5)
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.5)
+ '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.5)
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.5)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.5)
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.5)
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.5)
+ '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.5)
+ '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.23.5)
+ '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-async-generator-functions': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-classes': 7.23.5(@babel/core@7.23.5)
+ '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-for-of': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-modules-systemjs': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.23.5)
+ '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.23.5)
+ '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.23.5)
+ '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.23.5)
+ '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.23.5)
+ babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.23.5)
+ babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.23.5)
+ babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.23.5)
+ core-js-compat: 3.33.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.5):
+ resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/types': 7.23.5
+ esutils: 2.0.3
+ dev: true
+
+ /@babel/regjsgen@0.8.0:
+ resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==}
+ dev: true
+
+ /@babel/runtime@7.23.5:
+ resolution: {integrity: sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.0
+ dev: true
+
+ /@babel/template@7.22.15:
+ resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/parser': 7.23.5
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/traverse@7.23.5:
+ resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/parser': 7.23.5
+ '@babel/types': 7.23.5
+ debug: 4.3.4
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/types@7.23.5:
+ resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.23.4
+ '@babel/helper-validator-identifier': 7.22.20
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@braintree/sanitize-url@6.0.4:
+ resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==}
+ dev: true
+
+ /@esbuild/android-arm64@0.19.8:
+ resolution: {integrity: sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.19.8:
+ resolution: {integrity: sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.19.8:
+ resolution: {integrity: sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.19.8:
+ resolution: {integrity: sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.19.8:
+ resolution: {integrity: sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.19.8:
+ resolution: {integrity: sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.19.8:
+ resolution: {integrity: sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.19.8:
+ resolution: {integrity: sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.19.8:
+ resolution: {integrity: sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.19.8:
+ resolution: {integrity: sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.19.8:
+ resolution: {integrity: sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.19.8:
+ resolution: {integrity: sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.19.8:
+ resolution: {integrity: sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.19.8:
+ resolution: {integrity: sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.19.8:
+ resolution: {integrity: sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.19.8:
+ resolution: {integrity: sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.19.8:
+ resolution: {integrity: sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.19.8:
+ resolution: {integrity: sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.19.8:
+ resolution: {integrity: sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.19.8:
+ resolution: {integrity: sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.19.8:
+ resolution: {integrity: sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.19.8:
+ resolution: {integrity: sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/source-map@0.3.5:
+ resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.20:
+ resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /@lit-labs/ssr-dom-shim@1.1.2:
+ resolution: {integrity: sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==}
+ dev: true
+
+ /@lit/reactive-element@1.6.3:
+ resolution: {integrity: sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==}
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.1.2
+ dev: true
+
+ /@mdit-vue/plugin-component@1.0.0:
+ resolution: {integrity: sha512-ZXsJwxkG5yyTHARIYbR74cT4AZ0SfMokFFjiHYCbypHIeYWgJhso4+CZ8+3V9EWFG3EHlGoKNGqKp9chHnqntQ==}
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/plugin-frontmatter@1.0.0:
+ resolution: {integrity: sha512-MMA7Ny+YPZA7eDOY1t4E+rKuEWO39mzDdP/M68fKdXJU6VfcGkPr7gnpnJfW2QBJ5qIvMrK/3lDAA2JBy5TfpA==}
+ dependencies:
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ gray-matter: 4.0.3
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/plugin-headers@1.0.0:
+ resolution: {integrity: sha512-0rK/iKy6x13d/Pp5XxdLBshTD0+YjZvtHIaIV+JO+/H2WnOv7oaRgs48G5d44z3XJVUE2u6fNnTlI169fef0/A==}
+ dependencies:
+ '@mdit-vue/shared': 1.0.0
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/plugin-sfc@1.0.0:
+ resolution: {integrity: sha512-agMUe0fY4YHxsZivSvplBwRwrFvsIf/JNUJCAYq1+2Sg9+2hviTBZwjZDxYqHDHOVLtiNr+wuo68tE24mAx3AQ==}
+ dependencies:
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/plugin-title@1.0.0:
+ resolution: {integrity: sha512-8yC60fCZ95xcJ/cvJH4Lv43Rs4k+33UGyKrRWj5J8TNyMwUyGcwur0XyPM+ffJH4/Bzq4myZLsj/TTFSkXRxvw==}
+ dependencies:
+ '@mdit-vue/shared': 1.0.0
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/plugin-toc@1.0.0:
+ resolution: {integrity: sha512-WN8blfX0X/5Nolic0ClDWP7eVo9IB+U4g0jbycX3lolIZX5Bai1UpsD3QYZr5VVsPbQJMKMGvTrCEtCNTGvyWQ==}
+ dependencies:
+ '@mdit-vue/shared': 1.0.0
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/shared@1.0.0:
+ resolution: {integrity: sha512-nbYBfmEi+pR2Lm0Z6TMVX2/iBjfr/kGEsHW8CC0rQw+3+sG5dY6VG094HuFAkiAmmvZx9DZZb+7ZMWp9vkwCRw==}
+ dependencies:
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit-vue/types@1.0.0:
+ resolution: {integrity: sha512-xeF5+sHLzRNF7plbksywKCph4qli20l72of2fMlZQQ7RECvXYrRkE9+bjRFQCyULC7B8ydUYbpbkux5xJlVWyw==}
+ dev: true
+
+ /@mdit/plugin-alert@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-5+xY/F/aY22cqFslFgKXXBGYkjsBjUOpoyTMkW3xSIBa1Vp1t48RoNmsv1CULhJH/hlHhJU0NFSj4xplUbrI+w==}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-align@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-Yr1+bh2zeDm/lmeT72+oWD0UsU9rYQQG44gIOT+LaVqNN0Uj5mcFbhHAbgyX3O28yy+i3WpE41orezNzwLaGFg==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@mdit/plugin-container': 0.7.5(markdown-it@13.0.2)
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-attrs@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-sI6xFfpaA3IvX13Vn4jz8nVaiDihiRI9v6ZJCUrUKxuhOSi8L9+Ig77D8XsnN9I50tqNXAdTXIh1zvCd9r+DBA==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-container@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-2SyaDa/5Ndgbhdg5MOXZs5dUb0g/Kv3bkrwo2Xfk7XIyPFkItMNN3G1atpkmu/iHlEBghM6qTCBz/3H9X+mpjw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-demo@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-tlfgkT8NTEzK7MyoklwKKgd1244wzyZrkqhLSKq2k8ALDpy9KTa0G/QUlPcxJo9iO9JAAiY1yZrfYfFBLu6bPA==}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-figure@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-okCiYXfbxvLIYJIk9/Pe+S+OvbgDEq1GVdPi7yFLXmA3s6YDq89b1GUI7NSo1h+ZdajtIUElhXrll/dkFSJ+8Q==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-footnote@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-TO4nytkKgX3bKGZ+ViMfCB/4qXi6Za1kgI7KhjFJEolS3lUl+ykW7oxz9KFAh7TxIir6BblBwi9D4Tbap0bWyg==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-img-lazyload@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-Cpb4fiJO1zpnEX0nfhizOAZeqRdO7cL11iPz3J5liBmlqkhOpxz1ddAf8kfc4vaLAeNIK6hpgEDVHp/PInImLw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-img-mark@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-X46NDPCC9ZUGXD3+bGvr8jbebazL67pcGeXMA2y9uHhd0gS5yZrZw//P1d10Q+JllH57ccNpFpTdVIPFB0FNWA==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-img-size@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-c64l/xSLosjCJvquezhYif7I6Tc2Vnsi8wjuXYhwNYIpdLE0jbQrB6m8Hhw/RMzskm/NhseptIitUnSoDjgweg==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-include@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-U7fivuMk9NBpksD1BSrMFDVJwTVzxGg0GHfnmkJEobT35v6qIa6wvGyz7igHOrXRUF3Jh01sHGR3YGonja+CbQ==}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ upath: 2.0.1
+ dev: true
+
+ /@mdit/plugin-katex@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-6r+A5NesR55g6vITIS7zT/VnH+/mWU4GUlsutZo1DkktkEw4aAnJtkGy/8GAl/AdzDrN6qzwFF0jL1cyEOgh3g==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ katex: ^0.16.9
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ katex:
+ optional: true
+ markdown-it:
+ optional: true
+ dependencies:
+ '@mdit/plugin-tex': 0.7.5(markdown-it@13.0.2)
+ '@types/katex': 0.16.7
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-mark@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-vPiw8Gj3CLg1biwduXAyeDyLzCZ+Sowbee2JRmzK6ZbImRzNK+0p9wjRrLu7yjn2b8bR5n3iKQWZzw9Wh/ACBQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-mathjax@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-9DkfoDm3nbzLaZC5uoCz+fD3g0JVodh8d8xAeN2oa9Z0fw1FS58hJJ0tXh5JSxxbS6EYK8k6m8jujYIsc83fmA==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ mathjax-full: ^3.2.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ mathjax-full:
+ optional: true
+ dependencies:
+ '@mdit/plugin-tex': 0.7.5(markdown-it@13.0.2)
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ upath: 2.0.1
+ dev: true
+
+ /@mdit/plugin-stylize@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-+yJKp6iAdA69lP6MkScaBlowLReqXo0vMsKJ1mfdB6c78604Y8+SMAFhj1d2xmDgiysEFHZfnOR2E+XFOwr/ag==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-sub@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-0W/ra3chwbZ9apu/V7pYrr5SZzKSVn/v8cRYWwGwdBTLqtD+i343vkJPvw+BQZlZqVSOTYDmszExt/TAk/9Ehw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-sup@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-nVg1JZ1xgv0aUWHZl4AdCVyi9eHeZ11IsiqqaJ4dYvkU/HOKFqP0yO5Gcwj2rMRWVfveAqR0Hvl6I6X11ynmRg==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-tab@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-hAhp/dj0E67r/aycPcVVAd1Lhr6v/kwd1+kAdxClG1tENneUpl9QrLsJOj5ijrWCWfDpOsNtmK6o3v7Z3Guzgw==}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-tasklist@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-kBtHU4pUwwEMtSTdwU1Y+CMAGLLQONcnxoOFFVwW6u8BOTpIFBQR99VX9uBa6pV+JHgqeNYAlzFvkDA49Za4Ag==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-tex@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-76aRjqXZd5F5Xf20Z01uOwH98LkBhlyQqSjhN/BekJt72+iCIEsX8QyPDBtegniSPjA6z9kgb9ks1ap1w1ufGg==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@mdit/plugin-uml@0.7.5(markdown-it@13.0.2):
+ resolution: {integrity: sha512-xRuBr0mbueVYpV0BvdWO/VmqHbMeKfHflTN5dFazFFclk7a/5XR/XcmCJG0VaFHxDIWkSH7+BxcgjsugbSBcWQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ markdown-it: ^13.0.2
+ peerDependenciesMeta:
+ markdown-it:
+ optional: true
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.15.0
+ dev: true
+
+ /@rollup/plugin-babel@5.3.1(@babel/core@7.23.5)(rollup@2.79.1):
+ resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
+ engines: {node: '>= 10.0.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ '@types/babel__core': ^7.1.9
+ rollup: ^1.20.0||^2.0.0
+ peerDependenciesMeta:
+ '@types/babel__core':
+ optional: true
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-imports': 7.22.15
+ '@rollup/pluginutils': 3.1.0(rollup@2.79.1)
+ rollup: 2.79.1
+ dev: true
+
+ /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1):
+ resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==}
+ engines: {node: '>= 10.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0
+ dependencies:
+ '@rollup/pluginutils': 3.1.0(rollup@2.79.1)
+ '@types/resolve': 1.17.1
+ builtin-modules: 3.3.0
+ deepmerge: 4.3.1
+ is-module: 1.0.0
+ resolve: 1.22.8
+ rollup: 2.79.1
+ dev: true
+
+ /@rollup/plugin-replace@2.4.2(rollup@2.79.1):
+ resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==}
+ peerDependencies:
+ rollup: ^1.20.0 || ^2.0.0
+ dependencies:
+ '@rollup/pluginutils': 3.1.0(rollup@2.79.1)
+ magic-string: 0.25.9
+ rollup: 2.79.1
+ dev: true
+
+ /@rollup/pluginutils@3.1.0(rollup@2.79.1):
+ resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
+ engines: {node: '>= 8.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0
+ dependencies:
+ '@types/estree': 0.0.39
+ estree-walker: 1.0.1
+ picomatch: 2.3.1
+ rollup: 2.79.1
+ dev: true
+
+ /@rollup/rollup-android-arm-eabi@4.6.1:
+ resolution: {integrity: sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm64@4.6.1:
+ resolution: {integrity: sha512-1TKm25Rn20vr5aTGGZqo6E4mzPicCUD79k17EgTLAsXc1zysyi4xXKACfUbwyANEPAEIxkzwue6JZ+stYzWUTA==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-arm64@4.6.1:
+ resolution: {integrity: sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-x64@4.6.1:
+ resolution: {integrity: sha512-LoSU9Xu56isrkV2jLldcKspJ7sSXmZWkAxg7sW/RfF7GS4F5/v4EiqKSMCFbZtDu2Nc1gxxFdQdKwkKS4rwxNg==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.6.1:
+ resolution: {integrity: sha512-EfI3hzYAy5vFNDqpXsNxXcgRDcFHUWSx5nnRSCKwXuQlI5J9dD84g2Usw81n3FLBNsGCegKGwwTVsSKK9cooSQ==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.6.1:
+ resolution: {integrity: sha512-9lhc4UZstsegbNLhH0Zu6TqvDfmhGzuCWtcTFXY10VjLLUe4Mr0Ye2L3rrtHaDd/J5+tFMEuo5LTCSCMXWfUKw==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-musl@4.6.1:
+ resolution: {integrity: sha512-FfoOK1yP5ksX3wwZ4Zk1NgyGHZyuRhf99j64I5oEmirV8EFT7+OhUZEnP+x17lcP/QHJNWGsoJwrz4PJ9fBEXw==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.6.1:
+ resolution: {integrity: sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-musl@4.6.1:
+ resolution: {integrity: sha512-RkJVNVRM+piYy87HrKmhbexCHg3A6Z6MU0W9GHnJwBQNBeyhCJG9KDce4SAMdicQnpURggSvtbGo9xAWOfSvIQ==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-arm64-msvc@4.6.1:
+ resolution: {integrity: sha512-v2FVT6xfnnmTe3W9bJXl6r5KwJglMK/iRlkKiIFfO6ysKs0rDgz7Cwwf3tjldxQUrHL9INT/1r4VA0n9L/F1vQ==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-ia32-msvc@4.6.1:
+ resolution: {integrity: sha512-YEeOjxRyEjqcWphH9dyLbzgkF8wZSKAKUkldRY6dgNR5oKs2LZazqGB41cWJ4Iqqcy9/zqYgmzBkRoVz3Q9MLw==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-x64-msvc@4.6.1:
+ resolution: {integrity: sha512-0zfTlFAIhgz8V2G8STq8toAjsYYA6eci1hnXuyOTUFnymrtJwnS6uGKiv3v5UrPZkBlamLvrLV2iiaeqCKzb0A==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@sindresorhus/merge-streams@1.0.0:
+ resolution: {integrity: sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==}
+ engines: {node: '>=18'}
+ dev: true
+
+ /@stackblitz/sdk@1.9.0:
+ resolution: {integrity: sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==}
+ dev: true
+
+ /@surma/rollup-plugin-off-main-thread@2.2.3:
+ resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==}
+ dependencies:
+ ejs: 3.1.9
+ json5: 2.2.3
+ magic-string: 0.25.9
+ string.prototype.matchall: 4.0.10
+ dev: true
+
+ /@types/d3-scale-chromatic@3.0.3:
+ resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==}
+ dev: true
+
+ /@types/d3-scale@4.0.8:
+ resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==}
+ dependencies:
+ '@types/d3-time': 3.0.3
+ dev: true
+
+ /@types/d3-time@3.0.3:
+ resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==}
+ dev: true
+
+ /@types/debug@4.1.12:
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ dependencies:
+ '@types/ms': 0.7.34
+ dev: true
+
+ /@types/estree@0.0.39:
+ resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
+ dev: true
+
+ /@types/fs-extra@11.0.4:
+ resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
+ dependencies:
+ '@types/jsonfile': 6.1.4
+ '@types/node': 20.10.3
+ dev: true
+
+ /@types/hash-sum@1.0.2:
+ resolution: {integrity: sha512-UP28RddqY8xcU0SCEp9YKutQICXpaAq9N8U2klqF5hegGha7KzTOL8EdhIIV3bOSGBzjEpN9bU/d+nNZBdJYVw==}
+ dev: true
+
+ /@types/jsonfile@6.1.4:
+ resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
+ dependencies:
+ '@types/node': 20.10.3
+ dev: true
+
+ /@types/katex@0.16.7:
+ resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
+ dev: true
+
+ /@types/linkify-it@3.0.5:
+ resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==}
+ dev: true
+
+ /@types/markdown-it-emoji@2.0.4:
+ resolution: {integrity: sha512-H6ulk/ZmbDxOayPwI/leJzrmoW1YKX1Z+MVSCHXuYhvqckV4I/c+hPTf6UiqJyn2avWugfj30XroheEb6/Ekqg==}
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ dev: true
+
+ /@types/markdown-it@13.0.7:
+ resolution: {integrity: sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==}
+ dependencies:
+ '@types/linkify-it': 3.0.5
+ '@types/mdurl': 1.0.5
+ dev: true
+
+ /@types/mdast@3.0.15:
+ resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: true
+
+ /@types/mdurl@1.0.5:
+ resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
+ dev: true
+
+ /@types/ms@0.7.34:
+ resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
+ dev: true
+
+ /@types/node@17.0.45:
+ resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
+ dev: true
+
+ /@types/node@20.10.3:
+ resolution: {integrity: sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
+ /@types/resolve@1.17.1:
+ resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
+ dependencies:
+ '@types/node': 20.10.3
+ dev: true
+
+ /@types/sax@1.2.7:
+ resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
+ dependencies:
+ '@types/node': 17.0.45
+ dev: true
+
+ /@types/trusted-types@2.0.7:
+ resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+ dev: true
+
+ /@types/unist@2.0.10:
+ resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
+ dev: true
+
+ /@types/web-bluetooth@0.0.20:
+ resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
+ dev: true
+
+ /@vitejs/plugin-vue@4.5.1(vite@5.0.5)(vue@3.3.10):
+ resolution: {integrity: sha512-DaUzYFr+2UGDG7VSSdShKa9sIWYBa1LL8KC0MNOf2H5LjcTPjob0x8LbkqXWmAtbANJCkpiQTj66UVcQkN2s3g==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.0.0 || ^5.0.0
+ vue: ^3.2.25
+ dependencies:
+ vite: 5.0.5
+ vue: 3.3.10
+ dev: true
+
+ /@vue/compiler-core@3.3.10:
+ resolution: {integrity: sha512-doe0hODR1+i1menPkRzJ5MNR6G+9uiZHIknK3Zn5OcIztu6GGw7u0XUzf3AgB8h/dfsZC9eouzoLo3c3+N/cVA==}
+ dependencies:
+ '@babel/parser': 7.23.5
+ '@vue/shared': 3.3.10
+ estree-walker: 2.0.2
+ source-map-js: 1.0.2
+ dev: true
+
+ /@vue/compiler-dom@3.3.10:
+ resolution: {integrity: sha512-NCrqF5fm10GXZIK0GrEAauBqdy+F2LZRt3yNHzrYjpYBuRssQbuPLtSnSNjyR9luHKkWSH8we5LMB3g+4z2HvA==}
+ dependencies:
+ '@vue/compiler-core': 3.3.10
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /@vue/compiler-sfc@3.3.10:
+ resolution: {integrity: sha512-xpcTe7Rw7QefOTRFFTlcfzozccvjM40dT45JtrE3onGm/jBLZ0JhpKu3jkV7rbDFLeeagR/5RlJ2Y9SvyS0lAg==}
+ dependencies:
+ '@babel/parser': 7.23.5
+ '@vue/compiler-core': 3.3.10
+ '@vue/compiler-dom': 3.3.10
+ '@vue/compiler-ssr': 3.3.10
+ '@vue/reactivity-transform': 3.3.10
+ '@vue/shared': 3.3.10
+ estree-walker: 2.0.2
+ magic-string: 0.30.5
+ postcss: 8.4.32
+ source-map-js: 1.0.2
+ dev: true
+
+ /@vue/compiler-ssr@3.3.10:
+ resolution: {integrity: sha512-12iM4jA4GEbskwXMmPcskK5wImc2ohKm408+o9iox3tfN9qua8xL0THIZtoe9OJHnXP4eOWZpgCAAThEveNlqQ==}
+ dependencies:
+ '@vue/compiler-dom': 3.3.10
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /@vue/devtools-api@6.5.1:
+ resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
+ dev: true
+
+ /@vue/reactivity-transform@3.3.10:
+ resolution: {integrity: sha512-0xBdk+CKHWT+Gev8oZ63Tc0qFfj935YZx+UAynlutnrDZ4diFCVFMWixn65HzjE3S1iJppWOo6Tt1OzASH7VEg==}
+ dependencies:
+ '@babel/parser': 7.23.5
+ '@vue/compiler-core': 3.3.10
+ '@vue/shared': 3.3.10
+ estree-walker: 2.0.2
+ magic-string: 0.30.5
+ dev: true
+
+ /@vue/reactivity@3.3.10:
+ resolution: {integrity: sha512-H5Z7rOY/JLO+e5a6/FEXaQ1TMuOvY4LDVgT+/+HKubEAgs9qeeZ+NhADSeEtrNQeiKLDuzeKc8v0CUFpB6Pqgw==}
+ dependencies:
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /@vue/runtime-core@3.3.10:
+ resolution: {integrity: sha512-DZ0v31oTN4YHX9JEU5VW1LoIVgFovWgIVb30bWn9DG9a7oA415idcwsRNNajqTx8HQJyOaWfRKoyuP2P2TYIag==}
+ dependencies:
+ '@vue/reactivity': 3.3.10
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /@vue/runtime-dom@3.3.10:
+ resolution: {integrity: sha512-c/jKb3ny05KJcYk0j1m7Wbhrxq7mZYr06GhKykDMNRRR9S+/dGT8KpHuNQjv3/8U4JshfkAk6TpecPD3B21Ijw==}
+ dependencies:
+ '@vue/runtime-core': 3.3.10
+ '@vue/shared': 3.3.10
+ csstype: 3.1.2
+ dev: true
+
+ /@vue/server-renderer@3.3.10(vue@3.3.10):
+ resolution: {integrity: sha512-0i6ww3sBV3SKlF3YTjSVqKQ74xialMbjVYGy7cOTi7Imd8ediE7t72SK3qnvhrTAhOvlQhq6Bk6nFPdXxe0sAg==}
+ peerDependencies:
+ vue: 3.3.10
+ dependencies:
+ '@vue/compiler-ssr': 3.3.10
+ '@vue/shared': 3.3.10
+ vue: 3.3.10
+ dev: true
+
+ /@vue/shared@3.3.10:
+ resolution: {integrity: sha512-2y3Y2J1a3RhFa0WisHvACJR2ncvWiVHcP8t0Inxo+NKz+8RKO4ZV8eZgCxRgQoA6ITfV12L4E6POOL9HOU5nqw==}
+ dev: true
+
+ /@vuepress/bundler-vite@2.0.0-rc.0:
+ resolution: {integrity: sha512-rX8S8IYpqqlJfNPstS/joorpxXx/4WuE7+gDM31i2HUrxOKGZVzq8ZsRRRU2UdoTwHZSd3LpUS4sMtxE5xLK1A==}
+ dependencies:
+ '@vitejs/plugin-vue': 4.5.1(vite@5.0.5)(vue@3.3.10)
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ autoprefixer: 10.4.16(postcss@8.4.32)
+ connect-history-api-fallback: 2.0.0
+ postcss: 8.4.32
+ postcss-load-config: 4.0.2(postcss@8.4.32)
+ rollup: 4.6.1
+ vite: 5.0.5
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@types/node'
+ - '@vue/composition-api'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - ts-node
+ - typescript
+ dev: true
+
+ /@vuepress/cli@2.0.0-rc.0:
+ resolution: {integrity: sha512-XWSIFO9iOR7N4O2lXIwS5vZuLjU9WU/aGAtmhMWEMxrdMx7TQaJbgrfpTUEbHMf+cPI1DXBbUbtmkqIvtfOV0w==}
+ hasBin: true
+ dependencies:
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ cac: 6.7.14
+ chokidar: 3.5.3
+ envinfo: 7.11.0
+ esbuild: 0.19.8
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/client@2.0.0-rc.0:
+ resolution: {integrity: sha512-TwQx8hJgYONYxX+QltZ2aw9O5Ym6SKelfiUduuIRb555B1gece/jSVap3H/ZwyBhpgJMtG4+/Mrmf8nlDSHjvw==}
+ dependencies:
+ '@vue/devtools-api': 6.5.1
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - typescript
+ dev: true
+
+ /@vuepress/core@2.0.0-rc.0:
+ resolution: {integrity: sha512-uoOaZP1MdxZYJIAJcRcmYKKeCIVnxZeOuLMOOB9CPuAKSalT1RvJ1lztw6RX3q9SPnlqtSZPQXDncPAZivw4pA==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/markdown': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/markdown@2.0.0-rc.0:
+ resolution: {integrity: sha512-USmqdKKMT6ZFHYRztTjKUlO8qgGfnEygMAAq4AzC/uYXiEfrbMBLAWJhteyGS56P3rGLj0OPAhksE681bX/wOg==}
+ dependencies:
+ '@mdit-vue/plugin-component': 1.0.0
+ '@mdit-vue/plugin-frontmatter': 1.0.0
+ '@mdit-vue/plugin-headers': 1.0.0
+ '@mdit-vue/plugin-sfc': 1.0.0
+ '@mdit-vue/plugin-title': 1.0.0
+ '@mdit-vue/plugin-toc': 1.0.0
+ '@mdit-vue/shared': 1.0.0
+ '@mdit-vue/types': 1.0.0
+ '@types/markdown-it': 13.0.7
+ '@types/markdown-it-emoji': 2.0.4
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ markdown-it: 13.0.2
+ markdown-it-anchor: 8.6.7(@types/markdown-it@13.0.7)(markdown-it@13.0.2)
+ markdown-it-emoji: 2.0.2
+ mdurl: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vuepress/plugin-active-header-links@2.0.0-rc.0:
+ resolution: {integrity: sha512-UJdXLYNGL5Wjy5YGY8M2QgqT75bZ95EHebbqGi8twBdIJE9O+bM+dPJyYtAk2PIVqFORiw3Hj+PchsNSxdn9+g==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ ts-debounce: 4.0.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-back-to-top@2.0.0-rc.0:
+ resolution: {integrity: sha512-6GPfuzV5lkAnR00BxRUhqMXwMWt741alkq2R6bln4N8BneSOwEpX/7vi19MGf232aKdS/Va4pF5p0/nJ8Sed/g==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ ts-debounce: 4.0.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-container@2.0.0-rc.0:
+ resolution: {integrity: sha512-b7vrLN11YE7qiUDPfA3N9P7Z8fupe9Wbcr9KAE/bmfZ9VT4d6kzpVyoU7XHi99XngitsmnkaXP4aBvBF1c2AnA==}
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/markdown': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ markdown-it: 13.0.2
+ markdown-it-container: 3.0.0
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-external-link-icon@2.0.0-rc.0:
+ resolution: {integrity: sha512-o8bk0oIlj/BkKc02mq91XLDloq1VOz/8iNcRwKAeqBE6svXzdYiyoTGet0J/4iPuAetsCn75S57W6RioDJHMnQ==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/markdown': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-git@2.0.0-rc.0:
+ resolution: {integrity: sha512-r7UF77vZxaYeJQLygzodKv+15z3/dTLuGp4VcYO21W6BlJZvd4u9zqgiV7A//bZQvK4+3Hprylr0G3KgXqMewA==}
+ dependencies:
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ execa: 8.0.1
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-medium-zoom@2.0.0-rc.0:
+ resolution: {integrity: sha512-peU1lYKsmKikIe/0pkJuHzD/k6xW2TuqdvKVhV4I//aOE1WxsREKJ4ACcldmoIsnysoDydAUqKT6xDPGyDsH2g==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ medium-zoom: 1.1.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-nprogress@2.0.0-rc.0:
+ resolution: {integrity: sha512-rI+eK0Pg1KiZE+7hGmDUeSbgdWCid8Vnw0hFKNmjinDzGVmx4m03M6qfvclsI0SryH+lR7itZGLaR4gbTlrz/w==}
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-palette@2.0.0-rc.0:
+ resolution: {integrity: sha512-wW70SCp3/K7s1lln5YQsBGTog2WXaQv5piva5zhXcQ47YGf4aAJpThDa5C/ot4HhkPOKn8Iz5s0ckxXZzW8DIg==}
+ dependencies:
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ chokidar: 3.5.3
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-prismjs@2.0.0-rc.0:
+ resolution: {integrity: sha512-c5WRI7+FhVjdbymOKQ8F2KY/Bnv7aQtWScVk8vCMUimNi7v7Wff/A/i3KSFNz/tge3LxiAeH/Dc2WS/OnQXwCg==}
+ dependencies:
+ '@vuepress/core': 2.0.0-rc.0
+ prismjs: 1.29.0
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/plugin-theme-data@2.0.0-rc.0:
+ resolution: {integrity: sha512-FXY3/Ml+rM6gNKvwdBF6vKAcwnSvtXCzKgQwJAw3ppQTKUkLcbOxqM+h4d8bzHWAAvdnEvQFug5uEZgWllBQbA==}
+ dependencies:
+ '@vue/devtools-api': 6.5.1
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/shared@2.0.0-rc.0:
+ resolution: {integrity: sha512-ikdSfjRv5LGM1iv4HHwF9P6gqTjaFCXKPK+hzlkHFHNZO1GLqk7/BPc4F51tAG1s8TcLhUZc+54LrfgS7PkXXA==}
+ dependencies:
+ '@mdit-vue/types': 1.0.0
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /@vuepress/theme-default@2.0.0-rc.0:
+ resolution: {integrity: sha512-I8Y08evDmMuD1jh3NftPpFFSlCWOizQDJLjN7EQwcg7jiAP4A7c2REo6nBN2EmP24Mi7UrRM+RnytHR5V+pElA==}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/plugin-active-header-links': 2.0.0-rc.0
+ '@vuepress/plugin-back-to-top': 2.0.0-rc.0
+ '@vuepress/plugin-container': 2.0.0-rc.0
+ '@vuepress/plugin-external-link-icon': 2.0.0-rc.0
+ '@vuepress/plugin-git': 2.0.0-rc.0
+ '@vuepress/plugin-medium-zoom': 2.0.0-rc.0
+ '@vuepress/plugin-nprogress': 2.0.0-rc.0
+ '@vuepress/plugin-palette': 2.0.0-rc.0
+ '@vuepress/plugin-prismjs': 2.0.0-rc.0
+ '@vuepress/plugin-theme-data': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ sass: 1.69.5
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /@vuepress/utils@2.0.0-rc.0:
+ resolution: {integrity: sha512-Q1ay/woClDHcW0Qe91KsnHoupdNN0tp/vhjvVLuAYxlv/1Obii7hz9WFcajyyGEhmsYxdvG2sGmcxFA02tuKkw==}
+ dependencies:
+ '@types/debug': 4.1.12
+ '@types/fs-extra': 11.0.4
+ '@types/hash-sum': 1.0.2
+ '@vuepress/shared': 2.0.0-rc.0
+ debug: 4.3.4
+ fs-extra: 11.2.0
+ globby: 14.0.0
+ hash-sum: 2.0.0
+ ora: 7.0.1
+ picocolors: 1.0.0
+ upath: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vueuse/core@10.7.0(vue@3.3.10):
+ resolution: {integrity: sha512-4EUDESCHtwu44ZWK3Gc/hZUVhVo/ysvdtwocB5vcauSV4B7NiGY5972WnsojB3vRNdxvAt7kzJWE2h9h7C9d5w==}
+ dependencies:
+ '@types/web-bluetooth': 0.0.20
+ '@vueuse/metadata': 10.7.0
+ '@vueuse/shared': 10.7.0(vue@3.3.10)
+ vue-demi: 0.14.6(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
+ /@vueuse/metadata@10.7.0:
+ resolution: {integrity: sha512-GlaH7tKP2iBCZ3bHNZ6b0cl9g0CJK8lttkBNUX156gWvNYhTKEtbweWLm9rxCPIiwzYcr/5xML6T8ZUEt+DkvA==}
+ dev: true
+
+ /@vueuse/shared@10.7.0(vue@3.3.10):
+ resolution: {integrity: sha512-kc00uV6CiaTdc3i1CDC4a3lBxzaBE9AgYNtFN87B5OOscqeWElj/uza8qVDmk7/U8JbqoONLbtqiLJ5LGRuqlw==}
+ dependencies:
+ vue-demi: 0.14.6(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+ dev: true
+
+ /acorn@8.11.2:
+ resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ajv@8.12.0:
+ resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ json-schema-traverse: 1.0.0
+ require-from-string: 2.0.2
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ dev: true
+
+ /argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+ dependencies:
+ sprintf-js: 1.0.3
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.5
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.2:
+ resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-array-buffer: 3.0.2
+ is-shared-array-buffer: 1.0.2
+ dev: true
+
+ /artplayer@5.0.9:
+ resolution: {integrity: sha512-IM/DShYdmKFEA9jl08LYbTK2Jfz9s7qIjEH0xWjnxvVArUKZZKcoqwr6i54U0c4grtc/Uvb4wtCd78kvtSVlgw==}
+ dependencies:
+ option-validator: 2.0.6
+ dev: true
+
+ /async@3.2.5:
+ resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
+ dev: true
+
+ /at-least-node@1.0.0:
+ resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
+ engines: {node: '>= 4.0.0'}
+ dev: true
+
+ /autoprefixer@10.4.16(postcss@8.4.32):
+ resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.22.2
+ caniuse-lite: 1.0.30001566
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.32
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.23.5):
+ resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/core': 7.23.5
+ '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.5)
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /babel-plugin-polyfill-corejs3@0.8.6(@babel/core@7.23.5):
+ resolution: {integrity: sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.5)
+ core-js-compat: 3.33.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==}
+ peerDependencies:
+ '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.23.5)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /balloon-css@1.2.0:
+ resolution: {integrity: sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==}
+ dev: true
+
+ /base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ dev: true
+
+ /bcrypt-ts@5.0.0:
+ resolution: {integrity: sha512-0+VFzpOk0oIw8W8DfcCl0+xYbM04ib1u9IqkJCQQr+Vx8Pie4wzXmow+4zEnU0SP72QgPACDn0ARybH7q95Cbw==}
+ engines: {node: '>=18'}
+ dev: true
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /bl@5.1.0:
+ resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==}
+ dependencies:
+ buffer: 6.0.3
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ dev: true
+
+ /boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+ dev: true
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+ dev: true
+
+ /browserslist@4.22.2:
+ resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001566
+ electron-to-chromium: 1.4.603
+ node-releases: 2.0.14
+ update-browserslist-db: 1.0.13(browserslist@4.22.2)
+ dev: true
+
+ /buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ dev: true
+
+ /buffer@6.0.3:
+ resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+ dev: true
+
+ /builtin-modules@3.3.0:
+ resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /call-bind@1.0.5:
+ resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
+ dependencies:
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ set-function-length: 1.1.1
+ dev: true
+
+ /camelcase@5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /caniuse-lite@1.0.30001566:
+ resolution: {integrity: sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==}
+ dev: true
+
+ /chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chalk@5.3.0:
+ resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
+ engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
+ dev: true
+
+ /character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+ dev: true
+
+ /cheerio-select@2.1.0:
+ resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==}
+ dependencies:
+ boolbase: 1.0.0
+ css-select: 5.1.0
+ css-what: 6.1.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ dev: true
+
+ /cheerio@1.0.0-rc.12:
+ resolution: {integrity: sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==}
+ engines: {node: '>= 6'}
+ dependencies:
+ cheerio-select: 2.1.0
+ dom-serializer: 2.0.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ htmlparser2: 8.0.2
+ parse5: 7.1.2
+ parse5-htmlparser2-tree-adapter: 7.0.0
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /cli-cursor@4.0.0:
+ resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ restore-cursor: 4.0.0
+ dev: true
+
+ /cli-spinners@2.9.2:
+ resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /cliui@6.0.0:
+ resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 6.2.0
+ dev: true
+
+ /color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+ dev: true
+
+ /commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+ dev: true
+
+ /common-tags@1.8.2:
+ resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
+ engines: {node: '>=4.0.0'}
+ dev: true
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /connect-history-api-fallback@2.0.0:
+ resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==}
+ engines: {node: '>=0.8'}
+ dev: true
+
+ /convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ dev: true
+
+ /core-js-compat@3.33.3:
+ resolution: {integrity: sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow==}
+ dependencies:
+ browserslist: 4.22.2
+ dev: true
+
+ /cose-base@1.0.3:
+ resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==}
+ dependencies:
+ layout-base: 1.0.2
+ dev: true
+
+ /cose-base@2.2.0:
+ resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
+ dependencies:
+ layout-base: 2.0.1
+ dev: true
+
+ /create-codepen@1.0.1:
+ resolution: {integrity: sha512-XzSWwGCFNeOnNGp3KdCDGaKq4Cp1SvjzpPGQqO0tj1HT3BhksLdl/xQ2ZEY4+0MQ3m1I/K1Fvpm4GGMthtamyA==}
+ dev: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /crypto-random-string@2.0.0:
+ resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /css-select@5.1.0:
+ resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 6.1.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ nth-check: 2.1.1
+ dev: true
+
+ /css-what@6.1.0:
+ resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /csstype@3.1.2:
+ resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
+ dev: true
+
+ /cytoscape-cose-bilkent@4.1.0(cytoscape@3.27.0):
+ resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==}
+ peerDependencies:
+ cytoscape: ^3.2.0
+ dependencies:
+ cose-base: 1.0.3
+ cytoscape: 3.27.0
+ dev: true
+
+ /cytoscape-fcose@2.2.0(cytoscape@3.27.0):
+ resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==}
+ peerDependencies:
+ cytoscape: ^3.2.0
+ dependencies:
+ cose-base: 2.2.0
+ cytoscape: 3.27.0
+ dev: true
+
+ /cytoscape@3.27.0:
+ resolution: {integrity: sha512-pPZJilfX9BxESwujODz5pydeGi+FBrXq1rcaB1mfhFXXFJ9GjE6CNndAk+8jPzoXGD+16LtSS4xlYEIUiW4Abg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ heap: 0.2.7
+ lodash: 4.17.21
+ dev: true
+
+ /d3-array@2.12.1:
+ resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==}
+ dependencies:
+ internmap: 1.0.1
+ dev: true
+
+ /d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+ dependencies:
+ internmap: 2.0.3
+ dev: true
+
+ /d3-axis@3.0.0:
+ resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-brush@3.0.0:
+ resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+ dev: true
+
+ /d3-chord@3.0.1:
+ resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-path: 3.1.0
+ dev: true
+
+ /d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-contour@4.0.2:
+ resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ dev: true
+
+ /d3-delaunay@6.0.4:
+ resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
+ engines: {node: '>=12'}
+ dependencies:
+ delaunator: 5.0.0
+ dev: true
+
+ /d3-dispatch@3.0.1:
+ resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-drag@3.0.0:
+ resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-selection: 3.0.0
+ dev: true
+
+ /d3-dsv@3.0.1:
+ resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
+ engines: {node: '>=12'}
+ hasBin: true
+ dependencies:
+ commander: 7.2.0
+ iconv-lite: 0.6.3
+ rw: 1.3.3
+ dev: true
+
+ /d3-ease@3.0.1:
+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-fetch@3.0.1:
+ resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-dsv: 3.0.1
+ dev: true
+
+ /d3-force@3.0.0:
+ resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-timer: 3.0.1
+ dev: true
+
+ /d3-format@3.1.0:
+ resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-geo@3.1.0:
+ resolution: {integrity: sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ dev: true
+
+ /d3-hierarchy@3.1.2:
+ resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-color: 3.1.0
+ dev: true
+
+ /d3-path@1.0.9:
+ resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
+ dev: true
+
+ /d3-path@3.1.0:
+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-polygon@3.0.1:
+ resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-quadtree@3.0.1:
+ resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-random@3.0.1:
+ resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-sankey@0.12.3:
+ resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==}
+ dependencies:
+ d3-array: 2.12.1
+ d3-shape: 1.3.7
+ dev: true
+
+ /d3-scale-chromatic@3.0.0:
+ resolution: {integrity: sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-color: 3.1.0
+ d3-interpolate: 3.0.1
+ dev: true
+
+ /d3-scale@4.0.2:
+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ d3-format: 3.1.0
+ d3-interpolate: 3.0.1
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ dev: true
+
+ /d3-selection@3.0.0:
+ resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-shape@1.3.7:
+ resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
+ dependencies:
+ d3-path: 1.0.9
+ dev: true
+
+ /d3-shape@3.2.0:
+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-path: 3.1.0
+ dev: true
+
+ /d3-time-format@4.1.0:
+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-time: 3.1.0
+ dev: true
+
+ /d3-time@3.1.0:
+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ dev: true
+
+ /d3-timer@3.0.1:
+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /d3-transition@3.0.1(d3-selection@3.0.0):
+ resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ d3-selection: 2 - 3
+ dependencies:
+ d3-color: 3.1.0
+ d3-dispatch: 3.0.1
+ d3-ease: 3.0.1
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-timer: 3.0.1
+ dev: true
+
+ /d3-zoom@3.0.0:
+ resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+ dev: true
+
+ /d3@7.8.5:
+ resolution: {integrity: sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==}
+ engines: {node: '>=12'}
+ dependencies:
+ d3-array: 3.2.4
+ d3-axis: 3.0.0
+ d3-brush: 3.0.0
+ d3-chord: 3.0.1
+ d3-color: 3.1.0
+ d3-contour: 4.0.2
+ d3-delaunay: 6.0.4
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-dsv: 3.0.1
+ d3-ease: 3.0.1
+ d3-fetch: 3.0.1
+ d3-force: 3.0.0
+ d3-format: 3.1.0
+ d3-geo: 3.1.0
+ d3-hierarchy: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-path: 3.1.0
+ d3-polygon: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-random: 3.0.1
+ d3-scale: 4.0.2
+ d3-scale-chromatic: 3.0.0
+ d3-selection: 3.0.0
+ d3-shape: 3.2.0
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ d3-timer: 3.0.1
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+ d3-zoom: 3.0.0
+ dev: true
+
+ /dagre-d3-es@7.0.10:
+ resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==}
+ dependencies:
+ d3: 7.8.5
+ lodash-es: 4.17.21
+ dev: true
+
+ /dayjs@1.11.10:
+ resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
+ dev: true
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /decamelize@1.2.0:
+ resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /decode-named-character-reference@1.0.2:
+ resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
+ dependencies:
+ character-entities: 2.0.2
+ dev: true
+
+ /deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /define-data-property@1.1.1:
+ resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ has-property-descriptors: 1.0.1
+ object-keys: 1.1.1
+ dev: true
+
+ /delaunator@5.0.0:
+ resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==}
+ dependencies:
+ robust-predicates: 3.0.2
+ dev: true
+
+ /dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /diff@5.1.0:
+ resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
+ engines: {node: '>=0.3.1'}
+ dev: true
+
+ /dijkstrajs@1.0.3:
+ resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
+ dev: true
+
+ /dom-serializer@2.0.0:
+ resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ entities: 4.5.0
+ dev: true
+
+ /domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ dev: true
+
+ /domhandler@5.0.3:
+ resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
+ engines: {node: '>= 4'}
+ dependencies:
+ domelementtype: 2.3.0
+ dev: true
+
+ /dompurify@3.0.6:
+ resolution: {integrity: sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==}
+ dev: true
+
+ /domutils@3.1.0:
+ resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
+ dependencies:
+ dom-serializer: 2.0.0
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ dev: true
+
+ /ejs@3.1.9:
+ resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+ dependencies:
+ jake: 10.8.7
+ dev: true
+
+ /electron-to-chromium@1.4.603:
+ resolution: {integrity: sha512-Dvo5OGjnl7AZTU632dFJtWj0uJK835eeOVQIuRcmBmsFsTNn3cL05FqOyHAfGQDIoHfLhyJ1Tya3PJ0ceMz54g==}
+ dev: true
+
+ /elkjs@0.8.2:
+ resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==}
+ dev: true
+
+ /emoji-regex@10.3.0:
+ resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==}
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /encode-utf8@1.0.3:
+ resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==}
+ dev: true
+
+ /entities@3.0.1:
+ resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
+ engines: {node: '>=0.12'}
+ dev: true
+
+ /entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+ dev: true
+
+ /envinfo@7.11.0:
+ resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /es-abstract@1.22.3:
+ resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ arraybuffer.prototype.slice: 1.0.2
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ es-set-tostringtag: 2.0.2
+ es-to-primitive: 1.2.1
+ function.prototype.name: 1.1.6
+ get-intrinsic: 1.2.2
+ get-symbol-description: 1.0.0
+ globalthis: 1.0.3
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ internal-slot: 1.0.6
+ is-array-buffer: 3.0.2
+ is-callable: 1.2.7
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-typed-array: 1.1.12
+ is-weakref: 1.0.2
+ object-inspect: 1.13.1
+ object-keys: 1.1.1
+ object.assign: 4.1.5
+ regexp.prototype.flags: 1.5.1
+ safe-array-concat: 1.0.1
+ safe-regex-test: 1.0.0
+ string.prototype.trim: 1.2.8
+ string.prototype.trimend: 1.0.7
+ string.prototype.trimstart: 1.0.7
+ typed-array-buffer: 1.0.0
+ typed-array-byte-length: 1.0.0
+ typed-array-byte-offset: 1.0.0
+ typed-array-length: 1.0.4
+ unbox-primitive: 1.0.2
+ which-typed-array: 1.1.13
+ dev: true
+
+ /es-set-tostringtag@2.0.2:
+ resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ has-tostringtag: 1.0.0
+ hasown: 2.0.0
+ dev: true
+
+ /es-to-primitive@1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /esbuild@0.19.8:
+ resolution: {integrity: sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.19.8
+ '@esbuild/android-arm64': 0.19.8
+ '@esbuild/android-x64': 0.19.8
+ '@esbuild/darwin-arm64': 0.19.8
+ '@esbuild/darwin-x64': 0.19.8
+ '@esbuild/freebsd-arm64': 0.19.8
+ '@esbuild/freebsd-x64': 0.19.8
+ '@esbuild/linux-arm': 0.19.8
+ '@esbuild/linux-arm64': 0.19.8
+ '@esbuild/linux-ia32': 0.19.8
+ '@esbuild/linux-loong64': 0.19.8
+ '@esbuild/linux-mips64el': 0.19.8
+ '@esbuild/linux-ppc64': 0.19.8
+ '@esbuild/linux-riscv64': 0.19.8
+ '@esbuild/linux-s390x': 0.19.8
+ '@esbuild/linux-x64': 0.19.8
+ '@esbuild/netbsd-x64': 0.19.8
+ '@esbuild/openbsd-x64': 0.19.8
+ '@esbuild/sunos-x64': 0.19.8
+ '@esbuild/win32-arm64': 0.19.8
+ '@esbuild/win32-ia32': 0.19.8
+ '@esbuild/win32-x64': 0.19.8
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /estree-walker@1.0.1:
+ resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
+ dev: true
+
+ /estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /execa@8.0.1:
+ resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
+ engines: {node: '>=16.17'}
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 8.0.1
+ human-signals: 5.0.0
+ is-stream: 3.0.0
+ merge-stream: 2.0.0
+ npm-run-path: 5.1.0
+ onetime: 6.0.0
+ signal-exit: 4.1.0
+ strip-final-newline: 3.0.0
+ dev: true
+
+ /extend-shallow@2.0.1:
+ resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extendable: 0.1.1
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fastq@1.15.0:
+ resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
+ dependencies:
+ reusify: 1.0.4
+ dev: true
+
+ /fflate@0.8.1:
+ resolution: {integrity: sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==}
+ dev: true
+
+ /filelist@1.0.4:
+ resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+ dependencies:
+ minimatch: 5.1.6
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+ dev: true
+
+ /fs-extra@11.2.0:
+ resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==}
+ engines: {node: '>=14.14'}
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+ dev: true
+
+ /fs-extra@9.1.0:
+ resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ at-least-node: 1.0.0
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ dev: true
+
+ /function.prototype.name@1.1.6:
+ resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
+ /get-intrinsic@1.2.2:
+ resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
+ dependencies:
+ function-bind: 1.1.2
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ dev: true
+
+ /get-own-enumerable-property-symbols@3.0.2:
+ resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==}
+ dev: true
+
+ /get-stream@8.0.1:
+ resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
+ engines: {node: '>=16'}
+ dev: true
+
+ /get-symbol-description@1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /giscus@1.3.0:
+ resolution: {integrity: sha512-A3tVLgSmpnh2sX9uGjo9MbzmTTEJirSyFUPRvkipvy37y9rhxUYDoh9kO37QVrP7Sc7QuJ+gihB6apkO0yDyTw==}
+ dependencies:
+ lit: 2.8.0
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.1
+ dev: true
+
+ /globby@14.0.0:
+ resolution: {integrity: sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==}
+ engines: {node: '>=18'}
+ dependencies:
+ '@sindresorhus/merge-streams': 1.0.0
+ fast-glob: 3.3.2
+ ignore: 5.3.0
+ path-type: 5.0.0
+ slash: 5.1.0
+ unicorn-magic: 0.1.0
+ dev: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ dev: true
+
+ /gray-matter@4.0.3:
+ resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
+ engines: {node: '>=6.0'}
+ dependencies:
+ js-yaml: 3.14.1
+ kind-of: 6.0.3
+ section-matter: 1.0.0
+ strip-bom-string: 1.0.0
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.1:
+ resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /hash-sum@2.0.0:
+ resolution: {integrity: sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==}
+ dev: true
+
+ /hasown@2.0.0:
+ resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function-bind: 1.1.2
+ dev: true
+
+ /heap@0.2.7:
+ resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
+ dev: true
+
+ /htmlparser2@8.0.2:
+ resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ entities: 4.5.0
+ dev: true
+
+ /human-signals@5.0.0:
+ resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
+ engines: {node: '>=16.17.0'}
+ dev: true
+
+ /iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ safer-buffer: 2.1.2
+ dev: true
+
+ /idb@7.1.1:
+ resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==}
+ dev: true
+
+ /ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+ dev: true
+
+ /ignore@5.3.0:
+ resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /immutable@4.3.4:
+ resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /internal-slot@1.0.6:
+ resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ hasown: 2.0.0
+ side-channel: 1.0.4
+ dev: true
+
+ /internmap@1.0.1:
+ resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
+ dev: true
+
+ /internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+ dev: true
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.13.1:
+ resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ dependencies:
+ hasown: 2.0.0
+ dev: true
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-extendable@0.1.1:
+ resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-interactive@2.0.0:
+ resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /is-module@1.0.0:
+ resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+ dev: true
+
+ /is-negative-zero@2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-obj@1.0.1:
+ resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-regexp@1.0.0:
+ resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-stream@3.0.0:
+ resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.12:
+ resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.13
+ dev: true
+
+ /is-unicode-supported@1.3.0:
+ resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /is-weakref@1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /jake@10.8.7:
+ resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ async: 3.2.5
+ chalk: 4.1.2
+ filelist: 1.0.4
+ minimatch: 3.1.2
+ dev: true
+
+ /jest-worker@26.6.2:
+ resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
+ engines: {node: '>= 10.13.0'}
+ dependencies:
+ '@types/node': 20.10.3
+ merge-stream: 2.0.0
+ supports-color: 7.2.0
+ dev: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ dev: true
+
+ /js-yaml@3.14.1:
+ resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+ hasBin: true
+ dependencies:
+ argparse: 1.0.10
+ esprima: 4.0.1
+ dev: true
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jsesc@0.5.0:
+ resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
+ hasBin: true
+ dev: true
+
+ /jsesc@2.5.2:
+ resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /json-schema-traverse@1.0.0:
+ resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
+ dev: true
+
+ /json-schema@0.4.0:
+ resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
+ dev: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /jsonfile@6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+ dev: true
+
+ /jsonpointer@5.0.1:
+ resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /khroma@2.1.0:
+ resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
+ dev: true
+
+ /kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /kleur@4.1.5:
+ resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /layout-base@1.0.2:
+ resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
+ dev: true
+
+ /layout-base@2.0.1:
+ resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==}
+ dev: true
+
+ /leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /lilconfig@3.0.0:
+ resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /linkify-it@4.0.1:
+ resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
+ dependencies:
+ uc.micro: 1.0.6
+ dev: true
+
+ /lit-element@3.3.3:
+ resolution: {integrity: sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==}
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.1.2
+ '@lit/reactive-element': 1.6.3
+ lit-html: 2.8.0
+ dev: true
+
+ /lit-html@2.8.0:
+ resolution: {integrity: sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==}
+ dependencies:
+ '@types/trusted-types': 2.0.7
+ dev: true
+
+ /lit@2.8.0:
+ resolution: {integrity: sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==}
+ dependencies:
+ '@lit/reactive-element': 1.6.3
+ lit-element: 3.3.3
+ lit-html: 2.8.0
+ dev: true
+
+ /locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-locate: 4.1.0
+ dev: true
+
+ /lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+ dev: true
+
+ /lodash.debounce@4.0.8:
+ resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+ dev: true
+
+ /lodash.sortby@4.7.0:
+ resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
+ dev: true
+
+ /lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: true
+
+ /log-symbols@5.1.0:
+ resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==}
+ engines: {node: '>=12'}
+ dependencies:
+ chalk: 5.3.0
+ is-unicode-supported: 1.3.0
+ dev: true
+
+ /lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ dependencies:
+ yallist: 3.1.1
+ dev: true
+
+ /lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /magic-string@0.25.9:
+ resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+ dependencies:
+ sourcemap-codec: 1.4.8
+ dev: true
+
+ /magic-string@0.30.5:
+ resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /markdown-it-anchor@8.6.7(@types/markdown-it@13.0.7)(markdown-it@13.0.2):
+ resolution: {integrity: sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==}
+ peerDependencies:
+ '@types/markdown-it': '*'
+ markdown-it: '*'
+ dependencies:
+ '@types/markdown-it': 13.0.7
+ markdown-it: 13.0.2
+ dev: true
+
+ /markdown-it-container@3.0.0:
+ resolution: {integrity: sha512-y6oKTq4BB9OQuY/KLfk/O3ysFhB3IMYoIWhGJEidXt1NQFocFK2sA2t0NYZAMyMShAGL6x5OPIbrmXPIqaN9rw==}
+ dev: true
+
+ /markdown-it-emoji@2.0.2:
+ resolution: {integrity: sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==}
+ dev: true
+
+ /markdown-it@13.0.2:
+ resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ entities: 3.0.1
+ linkify-it: 4.0.1
+ mdurl: 1.0.1
+ uc.micro: 1.0.6
+ dev: true
+
+ /mdast-util-from-markdown@1.3.1:
+ resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ '@types/unist': 2.0.10
+ decode-named-character-reference: 1.0.2
+ mdast-util-to-string: 3.2.0
+ micromark: 3.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-decode-string: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ unist-util-stringify-position: 3.0.3
+ uvu: 0.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /mdast-util-to-string@3.2.0:
+ resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==}
+ dependencies:
+ '@types/mdast': 3.0.15
+ dev: true
+
+ /mdurl@1.0.1:
+ resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
+ dev: true
+
+ /medium-zoom@1.1.0:
+ resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==}
+ dev: true
+
+ /merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+ dev: true
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /mermaid@10.6.1:
+ resolution: {integrity: sha512-Hky0/RpOw/1il9X8AvzOEChfJtVvmXm+y7JML5C//ePYMy0/9jCEmW1E1g86x9oDfW9+iVEdTV/i+M6KWRNs4A==}
+ dependencies:
+ '@braintree/sanitize-url': 6.0.4
+ '@types/d3-scale': 4.0.8
+ '@types/d3-scale-chromatic': 3.0.3
+ cytoscape: 3.27.0
+ cytoscape-cose-bilkent: 4.1.0(cytoscape@3.27.0)
+ cytoscape-fcose: 2.2.0(cytoscape@3.27.0)
+ d3: 7.8.5
+ d3-sankey: 0.12.3
+ dagre-d3-es: 7.0.10
+ dayjs: 1.11.10
+ dompurify: 3.0.6
+ elkjs: 0.8.2
+ khroma: 2.1.0
+ lodash-es: 4.17.21
+ mdast-util-from-markdown: 1.3.1
+ non-layered-tidy-tree-layout: 2.0.2
+ stylis: 4.3.0
+ ts-dedent: 2.2.0
+ uuid: 9.0.1
+ web-worker: 1.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /micromark-core-commonmark@1.1.0:
+ resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
+ dependencies:
+ decode-named-character-reference: 1.0.2
+ micromark-factory-destination: 1.1.0
+ micromark-factory-label: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-factory-title: 1.1.0
+ micromark-factory-whitespace: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-classify-character: 1.1.0
+ micromark-util-html-tag-name: 1.2.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: true
+
+ /micromark-factory-destination@1.1.0:
+ resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-factory-label@1.1.0:
+ resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: true
+
+ /micromark-factory-space@1.1.0:
+ resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-factory-title@1.1.0:
+ resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-factory-whitespace@1.1.0:
+ resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
+ dependencies:
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-util-character@1.2.0:
+ resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-util-chunked@1.1.0:
+ resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: true
+
+ /micromark-util-classify-character@1.1.0:
+ resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-util-combine-extensions@1.1.0:
+ resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
+ dependencies:
+ micromark-util-chunked: 1.1.0
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-util-decode-numeric-character-reference@1.1.0:
+ resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: true
+
+ /micromark-util-decode-string@1.1.0:
+ resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
+ dependencies:
+ decode-named-character-reference: 1.0.2
+ micromark-util-character: 1.2.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-symbol: 1.1.0
+ dev: true
+
+ /micromark-util-encode@1.1.0:
+ resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
+ dev: true
+
+ /micromark-util-html-tag-name@1.2.0:
+ resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
+ dev: true
+
+ /micromark-util-normalize-identifier@1.1.0:
+ resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
+ dependencies:
+ micromark-util-symbol: 1.1.0
+ dev: true
+
+ /micromark-util-resolve-all@1.1.0:
+ resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
+ dependencies:
+ micromark-util-types: 1.1.0
+ dev: true
+
+ /micromark-util-sanitize-uri@1.2.0:
+ resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
+ dependencies:
+ micromark-util-character: 1.2.0
+ micromark-util-encode: 1.1.0
+ micromark-util-symbol: 1.1.0
+ dev: true
+
+ /micromark-util-subtokenize@1.1.0:
+ resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
+ dependencies:
+ micromark-util-chunked: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ dev: true
+
+ /micromark-util-symbol@1.1.0:
+ resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
+ dev: true
+
+ /micromark-util-types@1.1.0:
+ resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
+ dev: true
+
+ /micromark@3.2.0:
+ resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
+ dependencies:
+ '@types/debug': 4.1.12
+ debug: 4.3.4
+ decode-named-character-reference: 1.0.2
+ micromark-core-commonmark: 1.1.0
+ micromark-factory-space: 1.1.0
+ micromark-util-character: 1.2.0
+ micromark-util-chunked: 1.1.0
+ micromark-util-combine-extensions: 1.1.0
+ micromark-util-decode-numeric-character-reference: 1.1.0
+ micromark-util-encode: 1.1.0
+ micromark-util-normalize-identifier: 1.1.0
+ micromark-util-resolve-all: 1.1.0
+ micromark-util-sanitize-uri: 1.2.0
+ micromark-util-subtokenize: 1.1.0
+ micromark-util-symbol: 1.1.0
+ micromark-util-types: 1.1.0
+ uvu: 0.5.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+ dev: true
+
+ /mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /mimic-fn@4.0.0:
+ resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /mitt@3.0.1:
+ resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+ dev: true
+
+ /mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /node-releases@2.0.14:
+ resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ dev: true
+
+ /non-layered-tidy-tree-layout@2.0.2:
+ resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /npm-run-path@5.1.0:
+ resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ path-key: 4.0.0
+ dev: true
+
+ /nth-check@2.1.1:
+ resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+ dependencies:
+ boolbase: 1.0.0
+ dev: true
+
+ /object-inspect@1.13.1:
+ resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.5:
+ resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+ dependencies:
+ mimic-fn: 2.1.0
+ dev: true
+
+ /onetime@6.0.0:
+ resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ mimic-fn: 4.0.0
+ dev: true
+
+ /option-validator@2.0.6:
+ resolution: {integrity: sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==}
+ dependencies:
+ kind-of: 6.0.3
+ dev: true
+
+ /ora@7.0.1:
+ resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==}
+ engines: {node: '>=16'}
+ dependencies:
+ chalk: 5.3.0
+ cli-cursor: 4.0.0
+ cli-spinners: 2.9.2
+ is-interactive: 2.0.0
+ is-unicode-supported: 1.3.0
+ log-symbols: 5.1.0
+ stdin-discarder: 0.1.0
+ string-width: 6.1.0
+ strip-ansi: 7.1.0
+ dev: true
+
+ /p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+ dependencies:
+ p-try: 2.2.0
+ dev: true
+
+ /p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+ dependencies:
+ p-limit: 2.3.0
+ dev: true
+
+ /p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /parse5-htmlparser2-tree-adapter@7.0.0:
+ resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==}
+ dependencies:
+ domhandler: 5.0.3
+ parse5: 7.1.2
+ dev: true
+
+ /parse5@7.1.2:
+ resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
+ dependencies:
+ entities: 4.5.0
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /path-type@5.0.0:
+ resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /photoswipe@5.4.3:
+ resolution: {integrity: sha512-9UC6oJBK4oXFZ5HcdlcvGkfEHsVrmE4csUdCQhEjHYb3PvPLO3PG7UhnPuOgjxwmhq5s17Un5NUdum01LgBDng==}
+ engines: {node: '>= 0.12.0'}
+ dev: true
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /pngjs@5.0.0:
+ resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
+ engines: {node: '>=10.13.0'}
+ dev: true
+
+ /postcss-load-config@4.0.2(postcss@8.4.32):
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 3.0.0
+ postcss: 8.4.32
+ yaml: 2.3.4
+ dev: true
+
+ /postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ dev: true
+
+ /postcss@8.4.32:
+ resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /pretty-bytes@5.6.0:
+ resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /prismjs@1.29.0:
+ resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /qrcode@1.5.3:
+ resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==}
+ engines: {node: '>=10.13.0'}
+ hasBin: true
+ dependencies:
+ dijkstrajs: 1.0.3
+ encode-utf8: 1.0.3
+ pngjs: 5.0.0
+ yargs: 15.4.1
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /randombytes@2.1.0:
+ resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
+ dependencies:
+ safe-buffer: 5.2.1
+ dev: true
+
+ /readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /regenerate-unicode-properties@10.1.1:
+ resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==}
+ engines: {node: '>=4'}
+ dependencies:
+ regenerate: 1.4.2
+ dev: true
+
+ /regenerate@1.4.2:
+ resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==}
+ dev: true
+
+ /regenerator-runtime@0.14.0:
+ resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==}
+ dev: true
+
+ /regenerator-transform@0.15.2:
+ resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
+ dependencies:
+ '@babel/runtime': 7.23.5
+ dev: true
+
+ /regexp.prototype.flags@1.5.1:
+ resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ set-function-name: 2.0.1
+ dev: true
+
+ /regexpu-core@5.3.2:
+ resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ '@babel/regjsgen': 0.8.0
+ regenerate: 1.4.2
+ regenerate-unicode-properties: 10.1.1
+ regjsparser: 0.9.1
+ unicode-match-property-ecmascript: 2.0.0
+ unicode-match-property-value-ecmascript: 2.1.0
+ dev: true
+
+ /register-service-worker@1.7.2:
+ resolution: {integrity: sha512-CiD3ZSanZqcMPRhtfct5K9f7i3OLCcBBWsJjLh1gW9RO/nS94sVzY59iS+fgYBOBqaBpf4EzfqUF3j9IG+xo8A==}
+ dev: true
+
+ /regjsparser@0.9.1:
+ resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==}
+ hasBin: true
+ dependencies:
+ jsesc: 0.5.0
+ dev: true
+
+ /require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /require-from-string@2.0.2:
+ resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /require-main-filename@2.0.0:
+ resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+ dev: true
+
+ /resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /restore-cursor@4.0.0:
+ resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /robust-predicates@3.0.2:
+ resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
+ dev: true
+
+ /rollup-plugin-terser@7.0.2(rollup@2.79.1):
+ resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
+ deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
+ peerDependencies:
+ rollup: ^2.0.0
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ jest-worker: 26.6.2
+ rollup: 2.79.1
+ serialize-javascript: 4.0.0
+ terser: 5.25.0
+ dev: true
+
+ /rollup@2.79.1:
+ resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /rollup@4.6.1:
+ resolution: {integrity: sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.6.1
+ '@rollup/rollup-android-arm64': 4.6.1
+ '@rollup/rollup-darwin-arm64': 4.6.1
+ '@rollup/rollup-darwin-x64': 4.6.1
+ '@rollup/rollup-linux-arm-gnueabihf': 4.6.1
+ '@rollup/rollup-linux-arm64-gnu': 4.6.1
+ '@rollup/rollup-linux-arm64-musl': 4.6.1
+ '@rollup/rollup-linux-x64-gnu': 4.6.1
+ '@rollup/rollup-linux-x64-musl': 4.6.1
+ '@rollup/rollup-win32-arm64-msvc': 4.6.1
+ '@rollup/rollup-win32-ia32-msvc': 4.6.1
+ '@rollup/rollup-win32-x64-msvc': 4.6.1
+ fsevents: 2.3.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /rw@1.3.3:
+ resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
+ dev: true
+
+ /sade@1.8.1:
+ resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
+ engines: {node: '>=6'}
+ dependencies:
+ mri: 1.2.0
+ dev: true
+
+ /safe-array-concat@1.0.1:
+ resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ isarray: 2.0.5
+ dev: true
+
+ /safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+ dev: true
+
+ /safe-regex-test@1.0.0:
+ resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-regex: 1.1.4
+ dev: true
+
+ /safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+ dev: true
+
+ /sass@1.69.5:
+ resolution: {integrity: sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ chokidar: 3.5.3
+ immutable: 4.3.4
+ source-map-js: 1.0.2
+ dev: true
+
+ /sax@1.3.0:
+ resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
+ dev: true
+
+ /section-matter@1.0.0:
+ resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
+ engines: {node: '>=4'}
+ dependencies:
+ extend-shallow: 2.0.1
+ kind-of: 6.0.3
+ dev: true
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /semver@7.5.4:
+ resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /serialize-javascript@4.0.0:
+ resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==}
+ dependencies:
+ randombytes: 2.1.0
+ dev: true
+
+ /set-blocking@2.0.0:
+ resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+ dev: true
+
+ /set-function-length@1.1.1:
+ resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /set-function-name@2.0.1:
+ resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ object-inspect: 1.13.1
+ dev: true
+
+ /signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /sitemap@7.1.1:
+ resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==}
+ engines: {node: '>=12.0.0', npm: '>=5.6.0'}
+ hasBin: true
+ dependencies:
+ '@types/node': 17.0.45
+ '@types/sax': 1.2.7
+ arg: 5.0.2
+ sax: 1.3.0
+ dev: true
+
+ /slash@5.1.0:
+ resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
+ engines: {node: '>=14.16'}
+ dev: true
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+ dev: true
+
+ /source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map@0.8.0-beta.0:
+ resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
+ engines: {node: '>= 8'}
+ dependencies:
+ whatwg-url: 7.1.0
+ dev: true
+
+ /sourcemap-codec@1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ deprecated: Please use @jridgewell/sourcemap-codec instead
+ dev: true
+
+ /sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+ dev: true
+
+ /stdin-discarder@0.1.0:
+ resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ bl: 5.1.0
+ dev: true
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string-width@6.1.0:
+ resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==}
+ engines: {node: '>=16'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 10.3.0
+ strip-ansi: 7.1.0
+ dev: true
+
+ /string.prototype.matchall@4.0.10:
+ resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ regexp.prototype.flags: 1.5.1
+ set-function-name: 2.0.1
+ side-channel: 1.0.4
+ dev: true
+
+ /string.prototype.trim@1.2.8:
+ resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimend@1.0.7:
+ resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimstart@1.0.7:
+ resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ dependencies:
+ safe-buffer: 5.2.1
+ dev: true
+
+ /stringify-object@3.3.0:
+ resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==}
+ engines: {node: '>=4'}
+ dependencies:
+ get-own-enumerable-property-symbols: 3.0.2
+ is-obj: 1.0.1
+ is-regexp: 1.0.0
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+ dev: true
+
+ /strip-bom-string@1.0.0:
+ resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /strip-comments@2.0.1:
+ resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /strip-final-newline@3.0.0:
+ resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /striptags@3.2.0:
+ resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==}
+ dev: true
+
+ /stylis@4.3.0:
+ resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==}
+ dev: true
+
+ /supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /temp-dir@2.0.0:
+ resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /tempy@0.6.0:
+ resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==}
+ engines: {node: '>=10'}
+ dependencies:
+ is-stream: 2.0.1
+ temp-dir: 2.0.0
+ type-fest: 0.16.0
+ unique-string: 2.0.0
+ dev: true
+
+ /terser@5.25.0:
+ resolution: {integrity: sha512-we0I9SIsfvNUMP77zC9HG+MylwYYsGFSBG8qm+13oud2Yh+O104y614FRbyjpxys16jZwot72Fpi827YvGzuqg==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/source-map': 0.3.5
+ acorn: 8.11.2
+ commander: 2.20.3
+ source-map-support: 0.5.21
+ dev: true
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /tr46@1.0.1:
+ resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /ts-debounce@4.0.0:
+ resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==}
+ dev: true
+
+ /ts-dedent@2.2.0:
+ resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
+ engines: {node: '>=6.10'}
+ dev: true
+
+ /type-fest@0.16.0:
+ resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.0:
+ resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-length@1.0.0:
+ resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-offset@1.0.0:
+ resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-length@1.0.4:
+ resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ is-typed-array: 1.1.12
+ dev: true
+
+ /uc.micro@1.0.6:
+ resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
+ dev: true
+
+ /unbox-primitive@1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.5
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
+ /unicode-canonical-property-names-ecmascript@2.0.0:
+ resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /unicode-match-property-ecmascript@2.0.0:
+ resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==}
+ engines: {node: '>=4'}
+ dependencies:
+ unicode-canonical-property-names-ecmascript: 2.0.0
+ unicode-property-aliases-ecmascript: 2.1.0
+ dev: true
+
+ /unicode-match-property-value-ecmascript@2.1.0:
+ resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /unicode-property-aliases-ecmascript@2.1.0:
+ resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /unicorn-magic@0.1.0:
+ resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
+ engines: {node: '>=18'}
+ dev: true
+
+ /unique-string@2.0.0:
+ resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
+ engines: {node: '>=8'}
+ dependencies:
+ crypto-random-string: 2.0.0
+ dev: true
+
+ /unist-util-stringify-position@3.0.3:
+ resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==}
+ dependencies:
+ '@types/unist': 2.0.10
+ dev: true
+
+ /universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+ dev: true
+
+ /upath@1.2.0:
+ resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /upath@2.0.1:
+ resolution: {integrity: sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /update-browserslist-db@1.0.13(browserslist@4.22.2):
+ resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.22.2
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: true
+
+ /uuid@9.0.1:
+ resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
+ hasBin: true
+ dev: true
+
+ /uvu@0.5.6:
+ resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
+ engines: {node: '>=8'}
+ hasBin: true
+ dependencies:
+ dequal: 2.0.3
+ diff: 5.1.0
+ kleur: 4.1.5
+ sade: 1.8.1
+ dev: true
+
+ /vite@5.0.5:
+ resolution: {integrity: sha512-OekeWqR9Ls56f3zd4CaxzbbS11gqYkEiBtnWFFgYR2WV8oPJRRKq0mpskYy/XaoCL3L7VINDhqqOMNDiYdGvGg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ esbuild: 0.19.8
+ postcss: 8.4.32
+ rollup: 4.6.1
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /vue-demi@0.14.6(vue@3.3.10):
+ resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.3.10
+ dev: true
+
+ /vue-router@4.2.5(vue@3.3.10):
+ resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==}
+ peerDependencies:
+ vue: ^3.2.0
+ dependencies:
+ '@vue/devtools-api': 6.5.1
+ vue: 3.3.10
+ dev: true
+
+ /vue@3.3.10:
+ resolution: {integrity: sha512-zg6SIXZdTBwiqCw/1p+m04VyHjLfwtjwz8N57sPaBhEex31ND0RYECVOC1YrRwMRmxFf5T1dabl6SGUbMKKuVw==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@vue/compiler-dom': 3.3.10
+ '@vue/compiler-sfc': 3.3.10
+ '@vue/runtime-dom': 3.3.10
+ '@vue/server-renderer': 3.3.10(vue@3.3.10)
+ '@vue/shared': 3.3.10
+ dev: true
+
+ /vuepress-plugin-auto-catalog@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-PD/E5f42o2Z1i/g8WTdpFRZWPwAGj/PLkNVsITnyalqgLWFSJ0nYptEbffvLcOq1yJXNwxaAiWx/mZt8xV7nYw==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-components: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - dashjs
+ - hls.js
+ - mpegts.js
+ - plyr
+ - supports-color
+ - typescript
+ - vidstack
+ dev: true
+
+ /vuepress-plugin-blog2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-YzEEAI3hEkuCfWw2x54z11Z180RVAoMxvv5Mc0CgzbAIe9oGjSpbbRq3+PSX8EEEzn1lnHw8E5L9+ix3WI4Szg==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ chokidar: 3.5.3
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-comment2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-eREPtXX2JUxjqwWUpx6iJ5bKLEG5BVndhBFOjxm7yeyg0SWLCDHmuv8odZ5DTjL50k5hRuP1jVJkB7Caonkv+Q==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ '@waline/client': ^2.15.8
+ artalk: ^2.6.4
+ sass-loader: ^13.3.2
+ twikoo: ^1.6.26
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ '@waline/client':
+ optional: true
+ artalk:
+ optional: true
+ sass-loader:
+ optional: true
+ twikoo:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ giscus: 1.3.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-components@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-ejTbnaOmYvPlX1FwzlD8v/v8/hUGld3QzKfcvFkhHVn4ddhze5/NQj3cqHFfnT7fR23UKs8BI7L1L/0SFZiFGA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ dashjs: ^4.7.2
+ hls.js: ^1.4.12
+ mpegts.js: ^1.7.3
+ plyr: ^3.7.8
+ sass-loader: ^13.3.2
+ vidstack: ^1.8.1
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ dashjs:
+ optional: true
+ hls.js:
+ optional: true
+ mpegts.js:
+ optional: true
+ plyr:
+ optional: true
+ sass-loader:
+ optional: true
+ vidstack:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@stackblitz/sdk': 1.9.0
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ artplayer: 5.0.9
+ balloon-css: 1.2.0
+ create-codepen: 1.0.1
+ qrcode: 1.5.3
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-reading-time2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-copy-code2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-+wvfD54h4CMZPRl5pat5OP8dpl1PlXHYwY7Eba69GYXAtjj55L5IFva+FWWfSgyMFcdzWMkeNxNZK4bIjHqqXw==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ balloon-css: 1.2.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-copyright2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-6xJ14bVcaxNciC0UTdvaHg1R/uh5BUUA/UFOBYqYamhzveyQrgSInleghmYcbTH8hTh3+V5PCOLJENhH6wU7zQ==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-feed2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-xuMi9YAw8i/uRrwvQ+1hIdtVs2NXmi6g6YbCU6wuX1Ig1U/tKGUg4fNzA2M6w3Mg8fpA60fDY4FUpDmN05FpBA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ cheerio: 1.0.0-rc.12
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ xml-js: 1.6.11
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-md-enhance@2.0.0-rc.2(mermaid@10.6.1)(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-5yqU18oyYbn//n/bDSFBa3uLNgnuB3i+0BjcI0pVeV+eejHW31O8cLKKuoYlGiWlQrChiRWfNe/RyAMa9H1lmA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ '@types/reveal.js': ^4.4.5
+ '@vue/repl': ^3.0.0
+ chart.js: ^4.4.0
+ echarts: ^5.4.3
+ flowchart.ts: ^2.0.0
+ katex: ^0.16.9
+ kotlin-playground: ^1.29.0
+ markmap-lib: ^0.15.7
+ markmap-toolbar: ^0.15.6
+ markmap-view: ^0.15.6
+ mathjax-full: ^3.2.2
+ mermaid: ^10.6.1
+ reveal.js: ^5.0.2
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ '@types/reveal.js':
+ optional: true
+ '@vue/repl':
+ optional: true
+ chart.js:
+ optional: true
+ echarts:
+ optional: true
+ flowchart.ts:
+ optional: true
+ katex:
+ optional: true
+ kotlin-playground:
+ optional: true
+ markmap-lib:
+ optional: true
+ markmap-toolbar:
+ optional: true
+ markmap-view:
+ optional: true
+ mathjax-full:
+ optional: true
+ mermaid:
+ optional: true
+ reveal.js:
+ optional: true
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@mdit/plugin-alert': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-align': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-attrs': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-container': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-demo': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-figure': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-footnote': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-img-lazyload': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-img-mark': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-img-size': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-include': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-katex': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-mark': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-mathjax': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-stylize': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-sub': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-sup': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-tab': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-tasklist': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-tex': 0.7.5(markdown-it@13.0.2)
+ '@mdit/plugin-uml': 0.7.5(markdown-it@13.0.2)
+ '@types/markdown-it': 13.0.7
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ balloon-css: 1.2.0
+ js-yaml: 4.1.0
+ markdown-it: 13.0.2
+ mermaid: 10.6.1
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-photo-swipe@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-D2ipqEHsVfU3k4cYIi4CWTZiI+KwnZ1ywfgo55IYV9JmiCBbhhK47iAdq66BbUEyv0y1oKVq7ZlDznFW+KCGDg==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ photoswipe: 5.4.3
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-pwa2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-a8XMjR9UOCF1y5eGO3cTfznIDD2PgioreZrgI5FWCJRgZwXwcP1P1LohI3cQq6jXd8L3ZKpDxBSioSQMmBuD8g==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ mitt: 3.0.1
+ register-service-worker: 1.7.2
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ workbox-build: 7.0.0
+ transitivePeerDependencies:
+ - '@types/babel__core'
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-reading-time2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-EuMXOOsZh9YRC4yH7edeoNbCjsc/aekQ24HJ+zgOnDZWpF4HfQ6MYYZTM4KVJDxwCGCF8/o93z0ux8VP0PbJ4A==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ vue: 3.3.10
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-rtl@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-TUJjnPrOwWLsOYhwhoBUzVKySsB/dUW8pr2Azval96gombpnml3r8xt1b3pF1bV6vDP9o2ZZaYV6YBRe8Zl3YQ==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vue: 3.3.10
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-sass-palette@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-CHPAsn/DfwgQjY6FpuuGZtc0PI3leKnN9yKhMGmwfAyrVuXd1+8IIWosG/6Ob38yLPiybmcp+3DlQNJPBGjxnA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ chokidar: 3.5.3
+ sass: 1.69.5
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-seo2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-9L3Te7RQHQIzkhwB26PHa6YmmY+kgL+IPB4529VwL78UwHTQcVVn7YVKGxweybAbf47fcTUCCA5kMkFZYYDl5w==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-plugin-sitemap2@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-2AwB5vvdjcjkCGiwXYS+elZRDGb3HnkXETPjkp2qZLM5sxlcFJVbEVOf8p1XN2nTReL7tdMT2hoKGrJEwTESeA==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ sitemap: 7.1.1
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-shared@2.0.0-rc.2(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-N1R/izhfxCtAWAqTFTcedOj6P4kvHhVKU/XARjeb/F9opU81u7X5jtyTQsOyc8nhdC+BfCV2iD/mnnF/02AL2w==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ cheerio: 1.0.0-rc.12
+ dayjs: 1.11.10
+ execa: 8.0.1
+ fflate: 0.8.1
+ gray-matter: 4.0.3
+ semver: 7.5.4
+ striptags: 3.2.0
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - supports-color
+ - typescript
+ dev: true
+
+ /vuepress-theme-hope@2.0.0-rc.2(mermaid@10.6.1)(vuepress@2.0.0-rc.0):
+ resolution: {integrity: sha512-rrKgxcwLdIdR/57hA9VDacrn+YP2FpMpSWUNwmRzrehj2tq3z0nFYn8bn1+qC0gPUoroVPHULx8MscwA6CyrjQ==}
+ engines: {node: '>=18.16.0', npm: '>=8', pnpm: '>=7', yarn: '>=2'}
+ peerDependencies:
+ sass-loader: ^13.3.2
+ vuepress: 2.0.0-rc.0
+ vuepress-vite: 2.0.0-rc.0
+ vuepress-webpack: 2.0.0-rc.0
+ peerDependenciesMeta:
+ sass-loader:
+ optional: true
+ vuepress:
+ optional: true
+ vuepress-vite:
+ optional: true
+ vuepress-webpack:
+ optional: true
+ dependencies:
+ '@vuepress/cli': 2.0.0-rc.0
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/plugin-active-header-links': 2.0.0-rc.0
+ '@vuepress/plugin-container': 2.0.0-rc.0
+ '@vuepress/plugin-external-link-icon': 2.0.0-rc.0
+ '@vuepress/plugin-git': 2.0.0-rc.0
+ '@vuepress/plugin-nprogress': 2.0.0-rc.0
+ '@vuepress/plugin-prismjs': 2.0.0-rc.0
+ '@vuepress/plugin-theme-data': 2.0.0-rc.0
+ '@vuepress/shared': 2.0.0-rc.0
+ '@vuepress/utils': 2.0.0-rc.0
+ '@vueuse/core': 10.7.0(vue@3.3.10)
+ balloon-css: 1.2.0
+ bcrypt-ts: 5.0.0
+ cheerio: 1.0.0-rc.12
+ chokidar: 3.5.3
+ gray-matter: 4.0.3
+ vue: 3.3.10
+ vue-router: 4.2.5(vue@3.3.10)
+ vuepress: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ vuepress-plugin-auto-catalog: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-blog2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-comment2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-components: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-copy-code2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-copyright2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-feed2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-md-enhance: 2.0.0-rc.2(mermaid@10.6.1)(vuepress@2.0.0-rc.0)
+ vuepress-plugin-photo-swipe: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-pwa2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-reading-time2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-rtl: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-sass-palette: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-seo2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-plugin-sitemap2: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ vuepress-shared: 2.0.0-rc.2(vuepress@2.0.0-rc.0)
+ transitivePeerDependencies:
+ - '@types/babel__core'
+ - '@types/reveal.js'
+ - '@vue/composition-api'
+ - '@vue/repl'
+ - '@waline/client'
+ - artalk
+ - chart.js
+ - dashjs
+ - echarts
+ - flowchart.ts
+ - hls.js
+ - katex
+ - kotlin-playground
+ - markmap-lib
+ - markmap-toolbar
+ - markmap-view
+ - mathjax-full
+ - mermaid
+ - mpegts.js
+ - plyr
+ - reveal.js
+ - supports-color
+ - twikoo
+ - typescript
+ - vidstack
+ dev: true
+
+ /vuepress-vite@2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10):
+ resolution: {integrity: sha512-+2XBejeiskPyr2raBeA2o4uDFDsjtadpUVmtio3qqFtQpOhidz/ORuiTLr2UfLtFn1ASIHP6Vy2YjQ0e/TeUVw==}
+ engines: {node: '>=18.16.0'}
+ hasBin: true
+ peerDependencies:
+ '@vuepress/client': 2.0.0-rc.0
+ vue: ^3.3.4
+ dependencies:
+ '@vuepress/bundler-vite': 2.0.0-rc.0
+ '@vuepress/cli': 2.0.0-rc.0
+ '@vuepress/client': 2.0.0-rc.0
+ '@vuepress/core': 2.0.0-rc.0
+ '@vuepress/theme-default': 2.0.0-rc.0
+ vue: 3.3.10
+ transitivePeerDependencies:
+ - '@types/node'
+ - '@vue/composition-api'
+ - less
+ - lightningcss
+ - sass
+ - sass-loader
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - ts-node
+ - typescript
+ dev: true
+
+ /vuepress@2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10):
+ resolution: {integrity: sha512-sydt/B7+pIw926G5PntYmptLkC5o2buXKh+WR1+P2KnsvkXU+UGnQrJJ0FBvu/4RNuY99tkUZd59nyPhEmRrCg==}
+ engines: {node: '>=18.16.0'}
+ hasBin: true
+ dependencies:
+ vuepress-vite: 2.0.0-rc.0(@vuepress/client@2.0.0-rc.0)(vue@3.3.10)
+ transitivePeerDependencies:
+ - '@types/node'
+ - '@vue/composition-api'
+ - '@vuepress/client'
+ - less
+ - lightningcss
+ - sass
+ - sass-loader
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - ts-node
+ - typescript
+ - vue
+ dev: true
+
+ /web-worker@1.2.0:
+ resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==}
+ dev: true
+
+ /webidl-conversions@4.0.2:
+ resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
+ dev: true
+
+ /whatwg-url@7.1.0:
+ resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
+ dependencies:
+ lodash.sortby: 4.7.0
+ tr46: 1.0.1
+ webidl-conversions: 4.0.2
+ dev: true
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-module@2.0.1:
+ resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+ dev: true
+
+ /which-typed-array@1.1.13:
+ resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /workbox-background-sync@7.0.0:
+ resolution: {integrity: sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==}
+ dependencies:
+ idb: 7.1.1
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-broadcast-update@7.0.0:
+ resolution: {integrity: sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-build@7.0.0:
+ resolution: {integrity: sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==}
+ engines: {node: '>=16.0.0'}
+ dependencies:
+ '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0)
+ '@babel/core': 7.23.5
+ '@babel/preset-env': 7.23.5(@babel/core@7.23.5)
+ '@babel/runtime': 7.23.5
+ '@rollup/plugin-babel': 5.3.1(@babel/core@7.23.5)(rollup@2.79.1)
+ '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1)
+ '@rollup/plugin-replace': 2.4.2(rollup@2.79.1)
+ '@surma/rollup-plugin-off-main-thread': 2.2.3
+ ajv: 8.12.0
+ common-tags: 1.8.2
+ fast-json-stable-stringify: 2.1.0
+ fs-extra: 9.1.0
+ glob: 7.2.3
+ lodash: 4.17.21
+ pretty-bytes: 5.6.0
+ rollup: 2.79.1
+ rollup-plugin-terser: 7.0.2(rollup@2.79.1)
+ source-map: 0.8.0-beta.0
+ stringify-object: 3.3.0
+ strip-comments: 2.0.1
+ tempy: 0.6.0
+ upath: 1.2.0
+ workbox-background-sync: 7.0.0
+ workbox-broadcast-update: 7.0.0
+ workbox-cacheable-response: 7.0.0
+ workbox-core: 7.0.0
+ workbox-expiration: 7.0.0
+ workbox-google-analytics: 7.0.0
+ workbox-navigation-preload: 7.0.0
+ workbox-precaching: 7.0.0
+ workbox-range-requests: 7.0.0
+ workbox-recipes: 7.0.0
+ workbox-routing: 7.0.0
+ workbox-strategies: 7.0.0
+ workbox-streams: 7.0.0
+ workbox-sw: 7.0.0
+ workbox-window: 7.0.0
+ transitivePeerDependencies:
+ - '@types/babel__core'
+ - supports-color
+ dev: true
+
+ /workbox-cacheable-response@7.0.0:
+ resolution: {integrity: sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-core@7.0.0:
+ resolution: {integrity: sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==}
+ dev: true
+
+ /workbox-expiration@7.0.0:
+ resolution: {integrity: sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==}
+ dependencies:
+ idb: 7.1.1
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-google-analytics@7.0.0:
+ resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
+ dependencies:
+ workbox-background-sync: 7.0.0
+ workbox-core: 7.0.0
+ workbox-routing: 7.0.0
+ workbox-strategies: 7.0.0
+ dev: true
+
+ /workbox-navigation-preload@7.0.0:
+ resolution: {integrity: sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-precaching@7.0.0:
+ resolution: {integrity: sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==}
+ dependencies:
+ workbox-core: 7.0.0
+ workbox-routing: 7.0.0
+ workbox-strategies: 7.0.0
+ dev: true
+
+ /workbox-range-requests@7.0.0:
+ resolution: {integrity: sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-recipes@7.0.0:
+ resolution: {integrity: sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==}
+ dependencies:
+ workbox-cacheable-response: 7.0.0
+ workbox-core: 7.0.0
+ workbox-expiration: 7.0.0
+ workbox-precaching: 7.0.0
+ workbox-routing: 7.0.0
+ workbox-strategies: 7.0.0
+ dev: true
+
+ /workbox-routing@7.0.0:
+ resolution: {integrity: sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-strategies@7.0.0:
+ resolution: {integrity: sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==}
+ dependencies:
+ workbox-core: 7.0.0
+ dev: true
+
+ /workbox-streams@7.0.0:
+ resolution: {integrity: sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==}
+ dependencies:
+ workbox-core: 7.0.0
+ workbox-routing: 7.0.0
+ dev: true
+
+ /workbox-sw@7.0.0:
+ resolution: {integrity: sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==}
+ dev: true
+
+ /workbox-window@7.0.0:
+ resolution: {integrity: sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==}
+ dependencies:
+ '@types/trusted-types': 2.0.7
+ workbox-core: 7.0.0
+ dev: true
+
+ /wrap-ansi@6.2.0:
+ resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /xml-js@1.6.11:
+ resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
+ hasBin: true
+ dependencies:
+ sax: 1.3.0
+ dev: true
+
+ /y18n@4.0.3:
+ resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+ dev: true
+
+ /yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ dev: true
+
+ /yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yaml@2.3.4:
+ resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
+ engines: {node: '>= 14'}
+ dev: true
+
+ /yargs-parser@18.1.3:
+ resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
+ engines: {node: '>=6'}
+ dependencies:
+ camelcase: 5.3.1
+ decamelize: 1.2.0
+ dev: true
+
+ /yargs@15.4.1:
+ resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
+ engines: {node: '>=8'}
+ dependencies:
+ cliui: 6.0.0
+ decamelize: 1.2.0
+ find-up: 4.1.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ require-main-filename: 2.0.0
+ set-blocking: 2.0.0
+ string-width: 4.2.3
+ which-module: 2.0.1
+ y18n: 4.0.3
+ yargs-parser: 18.1.3
+ dev: true
diff --git a/src/.vuepress/client.ts b/src/.vuepress/client.ts
deleted file mode 100644
index 18d1c49..0000000
--- a/src/.vuepress/client.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { defineClientConfig } from "@vuepress/client";
-import ProjectLink from "./components/ProjectLink.js";
-// import TelegramLink from "docs-shared/components/TelegramLink.js";
-//
-// import CustomBlogHome from "./layouts/CustomBlogHome.vue";
-// import SlotDemo from "./layouts/SlotDemo.vue";
-
-export default defineClientConfig({
- enhance: ({ app }) => {
- app.component("ProjectLink", ProjectLink);
- // app.component("TelegramLink", TelegramLink);
- },
- // layouts: { CustomBlogHome, SlotDemo },
-});
diff --git a/src/.vuepress/components/ProjectLink.ts b/src/.vuepress/components/ProjectLink.ts
deleted file mode 100644
index b05fa8a..0000000
--- a/src/.vuepress/components/ProjectLink.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { FunctionalComponent } from "vue";
-import { h } from "vue";
-
-const ProjectLink: FunctionalComponent = () =>
- h(
- "div",
- { class: "nav-item vp-repo" },
- h("a", {
- class: "vp-repo-link",
- href: "https://github.com/ZLMediaKit/ZLMediaKit",
- target: "_blank",
- rel: "noopener noreferrer",
- "aria-label": "Github",
- innerHTML:
- '',
- }),
- );
-
-ProjectLink.displayName = "ProjectLink";
-
-export default ProjectLink;
diff --git a/src/.vuepress/config.ts b/src/.vuepress/config.ts
index 60b15cb..2f6f51a 100644
--- a/src/.vuepress/config.ts
+++ b/src/.vuepress/config.ts
@@ -1,34 +1,33 @@
-import {defineUserConfig} from "vuepress";
-import {fs, getDirname, path} from "@vuepress/utils";
-import {viteBundler} from '@vuepress/bundler-vite'
+import { viteBundler } from "@vuepress/bundler-vite";
+import { path } from "@vuepress/utils";
+import { defineUserConfig } from "vuepress";
import theme from "./theme.js";
export default defineUserConfig({
- base: "/",
- head: [['link', { rel: 'icon', href: '/favicon.ico' }]],
- locales: {
- "/": {
- lang: "en-US",
- title: "ZLMediaKit",
- description: "Official documentation for ZLMediaKit",
- },
- "/zh/": {
- lang: "zh-CN",
- title: "ZLMediaKit",
- description: "ZLMediaKit 官方文档",
- },
+ base: "/",
+
+ locales: {
+ "/": {
+ lang: "en-US",
+ title: "ZLMediaKit",
+ description: "Official documentation for ZLMediaKit",
+ },
+ "/zh/": {
+ lang: "zh-CN",
+ title: "ZLMediaKit",
+ description: "ZLMediaKit 官方文档",
},
- bundler: viteBundler({
- viteOptions: {
- build: {
- cssCodeSplit: false,
- }
- },
- vuePluginOptions: {},
- }),
- theme,
+ },
+
+ bundler: viteBundler({
+ viteOptions: {
+ build: {
+ cssCodeSplit: false,
+ },
+ },
+ }),
+
+ theme,
- // Enable it with pwa
- // shouldPrefetch: false,
- clientConfigFile: path.resolve(__dirname, "./client.ts"),
+ shouldPrefetch: false,
});
diff --git a/src/.vuepress/theme.ts b/src/.vuepress/theme.ts
index 2318d45..47b258f 100644
--- a/src/.vuepress/theme.ts
+++ b/src/.vuepress/theme.ts
@@ -1,160 +1,121 @@
-import {hopeTheme} from "vuepress-theme-hope";
-import {enNavbar, zhNavbar} from "./navbar/index.js";
-import {enSidebar, zhSidebar} from "./sidebar/index.js";
+import { hopeTheme } from "vuepress-theme-hope";
+import { enNavbar, zhNavbar } from "./navbar/index.js";
+import { enSidebar, zhSidebar } from "./sidebar/index.js";
export default hopeTheme({
- hostname: "https://docs.ZLMediaKit.com",
-
- author: {
- name: "ZLMediaKit",
- url: "https://docs.ZLMediaKit.com",
+ hostname: "https://docs.ZLMediaKit.com",
+ logo: "/logo.svg",
+ favicon: "/favicon.ico",
+ iconAssets: "fontawesome-with-brands",
+
+ author: {
+ name: "ZLMediaKit",
+ url: "https://docs.ZLMediaKit.com",
+ },
+ repo: "ZLMediaKit/ZLMediaKit",
+ docsRepo: "ZLMediaKit/docs",
+ docsDir: "src",
+
+ navbarLayout: {
+ start: ["Brand"],
+ center: [],
+ end: ["Links", "Language", "Repo", "Outlook", "Search"],
+ },
+
+ locales: {
+ "/": {
+ // navbar
+ navbar: enNavbar,
+
+ // sidebar
+ sidebar: enSidebar,
+
+ footer: "MIT Licensed",
+
+ displayFooter: true,
+
+ metaLocales: {
+ editLink: "Edit this page on GitHub",
+ },
},
- iconAssets: "fontawesome-with-brands",
-
- logo: "/logo.svg",
-
- repo: "ZLMediaKit/docs",
-
- docsDir: "src",
- navbarLayout: {
- start: ["Brand"],
- center: [],
- end: ["Links", "Language","ProjectLink", "Outlook", "Search"],
- },
-
- locales: {
- "/": {
- // navbar
- navbar: enNavbar,
-
- // sidebar
- sidebar: enSidebar,
-
- footer: "MIT Licensed",
-
- displayFooter: true,
+ /**
+ * Chinese locale config
+ */
+ "/zh/": {
+ // navbar
+ navbar: zhNavbar,
- metaLocales: {
- editLink: "Edit this page on GitHub",
- },
- },
+ // sidebar
+ sidebar: zhSidebar,
- /**
- * Chinese locale config
- */
- "/zh/": {
- // navbar
- navbar: zhNavbar,
+ footer: "MIT Licensed",
- // sidebar
- sidebar: zhSidebar,
+ displayFooter: true,
- footer: "MIT Licensed",
-
- displayFooter: true,
+ // page meta
+ metaLocales: {
+ editLink: "在 GitHub 上编辑此页",
+ },
+ },
+ },
+
+ plugins: {
+ // You should generate and use your own comment service
+ comment: {
+ provider: "Giscus",
+ repo: "ZLMediaKit/docs",
+ repoId: "R_kgDOKboWmQ",
+ category: "Announcements",
+ categoryId: "DIC_kwDOKboWmc4CZ_77",
+ },
- // page meta
- metaLocales: {
- editLink: "在 GitHub 上编辑此页",
- },
- },
+ // All features are enabled for demo, only preserve features you need here
+ mdEnhance: {
+ figure: true,
+ imgLazyload: true,
+ imgSize: true,
+ mermaid: true,
},
- encrypt: {},
-
- plugins: {
- // You should generate and use your own comment service
- comment: {
- provider: "Giscus",
- repo: "ZLMediaKit/docs",
- repoId: "R_kgDOKboWmQ",
- category: "Announcements",
- categoryId: "DIC_kwDOKboWmc4CZ_77",
- },
- copyCode: {},
- // All features are enabled for demo, only preserve features you need here
- mdEnhance: {
- align: true,
- attrs: true,
- chart: true,
- codetabs: true,
- demo: true,
- echarts: true,
- figure: true,
- flowchart: true,
- gfm: true,
- imgLazyload: true,
- imgSize: true,
- include: true,
- katex: true,
- mark: true,
- mermaid: true,
- playground: {
- presets: ["ts", "vue"],
- },
- flowchartConfig: {
- width: "100%",
- },
- presentation: ["highlight", "math", "search", "notes", "zoom"],
- stylize: [
- {
- matcher: "Recommended",
- replacer: ({tag}) => {
- if (tag === "em")
- return {
- tag: "Badge",
- attrs: {type: "tip"},
- content: "Recommended",
- };
- },
- },
- ],
- sub: true,
- sup: true,
- tabs: true,
- vPre: true,
- vuePlayground: true,
- },
-
- // uncomment these if you want a pwa
- pwa: {
- favicon: "/favicon.ico",
- cacheHTML: true,
- cachePic: true,
- appendBase: true,
- apple: {
- icon: "/assets/icon/apple-touch-icon-152x152.png",
- statusBarColor: "black",
+ // uncomment these if you want a pwa
+ pwa: {
+ favicon: "/favicon.ico",
+ cacheHTML: true,
+ cachePic: true,
+ appendBase: true,
+ apple: {
+ icon: "/assets/icon/apple-touch-icon-152x152.png",
+ statusBarColor: "black",
+ },
+ msTile: {
+ image: "/assets/icon/ms-icon-144.png",
+ color: "#ffffff",
+ },
+ manifest: {
+ icons: [
+ {
+ src: "/assets/icon/chrome-192.png",
+ sizes: "192x192",
+ type: "image/png",
},
- msTile: {
- image: "/assets/icon/ms-icon-144.png",
- color: "#ffffff",
- },
- manifest: {
+ ],
+ shortcuts: [
+ {
+ name: "ZlMediaKit Docs",
+ short_name: "ZLM",
+ url: "/guide/",
icons: [
{
- src: "/assets/icon/chrome-192.png",
+ src: "/assets/icon/guide-maskable.png",
sizes: "192x192",
+ purpose: "maskable",
type: "image/png",
},
],
- shortcuts: [
- {
- name: "ZlMediaKit Docs",
- short_name: "ZLM",
- url: "/guide/",
- icons: [
- {
- src: "/assets/icon/guide-maskable.png",
- sizes: "192x192",
- purpose: "maskable",
- type: "image/png",
- },
- ],
- },
- ],
},
- },
+ ],
+ },
},
+ },
});
diff --git a/src/README.md b/src/README.md
index b1bfdeb..e28fd95 100644
--- a/src/README.md
+++ b/src/README.md
@@ -4,8 +4,6 @@ icon: home
title: Home
description: An high-performance, enterprise-level streaming media service framework based on C++11.
heroImage: /logo.png
-bgImage:
-bgImageDark:
bgImageStyle:
background-attachment: fixed
heroText: ZLMediaKit
@@ -22,8 +20,6 @@ highlights:
- header: Features
description: Cross-platform streaming media solution for mobile and embedded systems.
image: /assets/image/features.svg
- bgImage:
- bgImageDark:
bgImageStyle:
background-repeat: repeat
background-size: initial
@@ -31,80 +27,65 @@ highlights:
- title: Versatile Protocol Support
icon: bug-slash
details: Developed with C++11, avoiding the use of raw pointers, providing stable and reliable code with superior performance
- link:
- title: Supports multiple protocols
icon: box-archive
details: Supports multiple protocols(RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV/GB28181/HTTP-TS/WebSocket-TS/HTTP-fMP4/WebSocket-fMP4/MP4/WebRTC), and protocol conversion
- link:
- title: High Concurrency and Performance
icon: bolt
details: Developed with multiplexing/multithreading/asynchronous network IO models, providing excellent concurrency performance and supporting massive client connections.
- link:
- title: Proven Stability and Production Usage
icon: microscope
details: The code has undergone extensive stability and performance testing, and has been extensively used in production environments.
- link:
- title: Cross-Platform Compatibility
icon: linux
details: Supports all major platforms, including linux, macos, ios, android, and windows.
- link:
- title: Multiple Instruction Set Platforms
icon: microchip
details: Supports multiple instruction set platforms, such as x86, arm, risc-v, mips, Loongson, and Shenwei.
- link:
- title: Ultra-Fast Startup and Low Latency
icon: truck-fast
details: Provides ultra-fast startup, extremely low latency (within 500 milliseconds, and can be as low as 100 milliseconds), and excellent user experience.
- link:
- title: C API for Integration
icon: code
details: Provides a comprehensive standard C API that can be used as an SDK or called by other languages.
- link:
- title: Complete MediaServer Solution
icon: server
details: Provides a complete MediaServer server, which can be deployed directly as a commercial server without additional development.
- link:
- title: RESTful API and Web Hook
icon: file-code
details: Provides a complete restful api and web hook, supporting rich business logic.
- link:
- title: Bridging Video Surveillance
icon: video
details: Bridges the video surveillance protocol stack and the live streaming protocol stack, and provides comprehensive support for RTSP/RTMP.
- link:
- title: Full Support for Codecs
icon: box-open
details: Fully supports H265/H264/AAC/G711/OPUS.
- link:
- title: Advanced Functionality
icon: toolbox
details: Provides complete functions, including clustering, on-demand protocol conversion, on-demand push/pull streams, playback before publishing, and continuous publishing after disconnection.
- link:
- title: Ultimate Performance and Scalability
icon: chart-pie
details: Provides ultimate performance, supporting 10W-level players on a single machine and 100Gb/s-level IO bandwidth capability.
- link:
- title: Exclusive Features
icon: user-secret
details: Fully supports IPv6 networks and provides ultimate user experience with exclusive features.
- link:
-
copyright: false
-footer: Theme by VuePress Theme Hope | MIT Licensed,
+footer:
+ Theme by VuePress Theme Hope | MIT Licensed,
Copyright © 2019-present ZLMediaKit
---
diff --git a/src/guide/README.md b/src/guide/README.md
index 44b5cb2..9e288c6 100644
--- a/src/guide/README.md
+++ b/src/guide/README.md
@@ -1,26 +1,25 @@
---
title: Guide
icon: terminal
-
---
# An high-performance, enterprise-level streaming media service framework based on C++11.
+[![badge](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/ZLMediaKit/ZLMediaKit/blob/master/LICENSE)
+[![badge](https://img.shields.io/badge/language-c++-red.svg)](https://en.cppreference.com/)
+[![badge](https://img.shields.io/badge/platform-linux%20|%20macos%20|%20windows-blue.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://img.shields.io/badge/PRs-welcome-yellow.svg)](https://github.com/ZLMediaKit/ZLMediaKit/pulls)
-[![](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/ZLMediaKit/ZLMediaKit/blob/master/LICENSE)
-[![](https://img.shields.io/badge/language-c++-red.svg)](https://en.cppreference.com/)
-[![](https://img.shields.io/badge/platform-linux%20|%20macos%20|%20windows-blue.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://img.shields.io/badge/PRs-welcome-yellow.svg)](https://github.com/ZLMediaKit/ZLMediaKit/pulls)
-
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/android.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/linux.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/macos.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/windows.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/android.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/linux.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/macos.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/windows.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/docker.yml/badge.svg)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
-[![](https://img.shields.io/docker/pulls/zlmediakit/zlmediakit)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/docker.yml/badge.svg)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
+[![badge](https://img.shields.io/docker/pulls/zlmediakit/zlmediakit)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
## Project Features
+
- Developed with C++11, avoiding the use of raw pointers, providing stable and reliable code with superior performance.
- Supports multiple protocols (RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV/GB28181/HTTP-TS/WebSocket-TS/HTTP-fMP4/WebSocket-fMP4/MP4/WebRTC), and protocol conversion.
- Developed with multiplexing/multithreading/asynchronous network IO models, providing excellent concurrency performance and supporting massive client connections.
@@ -46,6 +45,7 @@ icon: terminal
- Network programming secondary development SDK.
## Feature List
+
### Overview of Features
```mermaid
@@ -87,23 +87,25 @@ flowchart TD
FMP4_LIVE-->WEBSOCKET_FMP4_P(WEBSOCKET-FMP4)
```
-- RTSP[S]
- - RTSP[S] server, supports RTMP/MP4/HLS to RTSP[S] conversion, supports devices such as Amazon Echo Show
- - RTSP[S] player, supports RTSP proxy, supports generating silent audio
- - RTSP[S] push client and server
+- RTSP\[S\]
+
+ - RTSP\[S\] server, supports RTMP/MP4/HLS to RTSP\[S\] conversion, supports devices such as Amazon Echo Show
+ - RTSP\[S\] player, supports RTSP proxy, supports generating silent audio
+ - RTSP\[S\] push client and server
- Supports four RTP transmission modes: `rtp over udp` `rtp over tcp` `rtp over http` `rtp multicast`
- Server/client fully supports Basic/Digest authentication, asynchronous configurable authentication interface
- Supports H265 encoding
- The server supports RTSP pushing (including `rtp over udp` and `rtp over tcp`)
- Supports H264/H265/AAC/G711/OPUS/MJPEG encoding. Other encodings can be forwarded but cannot be converted to protocol
-- RTMP[S]
- - RTMP[S] playback server, supports RTSP/MP4/HLS to RTMP conversion
- - RTMP[S] publishing server, supports recording and publishing streams
- - RTMP[S] player, supports RTMP proxy, supports generating silent audio
- - RTMP[S] push client
- - Supports http[s]-flv live streaming server
- - Supports http[s]-flv live streaming player
+- RTMP\[S\]
+
+ - RTMP\[S\] playback server, supports RTSP/MP4/HLS to RTMP conversion
+ - RTMP\[S\] publishing server, supports recording and publishing streams
+ - RTMP\[S\] player, supports RTMP proxy, supports generating silent audio
+ - RTMP\[S\] push client
+ - Supports http\[s\]-flv live streaming server
+ - Supports http\[s\]-flv live streaming player
- Supports websocket-flv live streaming
- Supports H264/H265/AAC/G711/OPUS encoding. Other encodings can be forwarded but cannot be converted to protocol
- Supports [RTMP-H265](https://github.com/ksvc/FFmpeg/wiki)
@@ -111,22 +113,26 @@ flowchart TD
- Supports [enhanced-rtmp(H265)](https://github.com/veovera/enhanced-rtmp)
- HLS
+
- Supports HLS file(mpegts/fmp4) generation and comes with an HTTP file server
- Through cookie tracking technology, it can simulate HLS playback as a long connection, which can achieve HLS on-demand pulling, playback statistics, and other businesses
- Supports HLS player and can pull HLS to rtsp/rtmp/mp4
- Supports H264/H265/AAC/G711/OPUS encoding
- TS
- - Supports http[s]-ts live streaming
- - Supports ws[s]-ts live streaming
+
+ - Supports http\[s\]-ts live streaming
+ - Supports ws\[s\]-ts live streaming
- Supports H264/H265/AAC/G711/OPUS encoding
- fMP4
- - Supports http[s]-fmp4 live streaming
- - Supports ws[s]-fmp4 live streaming
+
+ - Supports http\[s\]-fmp4 live streaming
+ - Supports ws\[s\]-fmp4 live streaming
- Supports H264/H265/AAC/G711/OPUS/MJPEG encoding
-- HTTP[S] and WebSocket
+- http\[s\] and WebSocket
+
- The server supports `directory index generation`, `file download`, `form submission requests`
- The client provides `file downloader (supports resume breakpoint)`, `interface requestor`, `file uploader`
- Complete HTTP API server, which can be used as a web backend development framework
@@ -134,8 +140,9 @@ flowchart TD
- Supports http client/server cookie
- Supports WebSocket server and client
- Supports http file access authentication
-
+
- GB28181 and RTP Streaming
+
- Supports UDP/TCP RTP (PS/TS/ES) streaming server, which can be converted to RTSP/RTMP/HLS and other protocols
- Supports RTSP/RTMP/HLS and other protocol conversion to RTP streaming client, supports TCP/UDP mode, provides corresponding RESTful API, supports active and passive modes
- Supports H264/H265/AAC/G711/OPUS encoding
@@ -145,6 +152,7 @@ flowchart TD
- Supports two-way voice intercom
- MP4 VOD and Recording
+
- Supports recording as FLV/HLS/MP4
- Supports MP4 file playback for RTSP/RTMP/HTTP-FLV/WS-FLV, supports seek
- Supports H264/H265/AAC/G711/OPUS encoding
@@ -189,9 +197,9 @@ It is recommended to compile on Ubuntu or macOS. Compiling on Windows is cumbers
You have three ways to use ZLMediaKit, namely:
- - 1. Use c api as sdk, please refer to [here](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include).
- - 2. Used as an independent streaming media server. If you don’t want to do c/c++ development, you can refer to [restful api](./media_server/restful_api.md) and [web hook](./media_server/web_hook_api.md).
- - 3. If you want to do c/c++ development and add business logic to increase functions, you can refer to the [test program] here (https://github.com/ZLMediaKit/ZLMediaKit/tree/master/tests).
+- 1. Use c api as sdk, please refer to [here](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include).
+- 2. Used as an independent streaming media server. If you don’t want to do c/c++ development, you can refer to [restful api](./media_server/restful_api.md) and [web hook](./media_server/web_hook_api.md).
+- 3. If you want to do c/c++ development and add business logic to increase functions, you can refer to the [test program] here (https://github.com/ZLMediaKit/ZLMediaKit/tree/master/tests).
## Docker image
diff --git a/src/guide/code/oncetoken.md b/src/guide/code/oncetoken.md
index d2f3ea0..35801d3 100644
--- a/src/guide/code/oncetoken.md
+++ b/src/guide/code/oncetoken.md
@@ -7,70 +7,72 @@ The `onceToken` primarily applies the RAII (Resource Acquisition Is Initializati
1. Used as a global variable to execute specific code during program loading, such as generating default configuration files:
- ```C++
- ////////////HLS-related configurations///////////
- namespace Hls {
- #define HLS_FIELD "hls."
- //HLS segment duration in seconds
- const string kSegmentDuration = HLS_FIELD"segDur";
- //Number of HLS segments
- const string kSegmentNum = HLS_FIELD"segNum";
- //Number of HLS segments retained on disk after removal from m3u8 file
- const string kSegmentRetain = HLS_FIELD"segRetain";
- //HLS file write buffer size
- const string kFileBufSize = HLS_FIELD"fileBufSize";
- //Recording file path
- const string kFilePath = HLS_FIELD"filePath";
-
- onceToken token([](){
- mINI::Instance()[kSegmentDuration] = 2;
- mINI::Instance()[kSegmentNum] = 3;
- mINI::Instance()[kSegmentRetain] = 5;
- mINI::Instance()[kFileBufSize] = 64 * 1024;
- mINI::Instance()[kFilePath] = "./www";
- },nullptr);
- } //namespace Hls
- ```
+ ```cpp
+ ////////////HLS-related configurations///////////
+ namespace Hls {
+ #define HLS_FIELD "hls."
+ //HLS segment duration in seconds
+ const string kSegmentDuration = HLS_FIELD"segDur";
+ //Number of HLS segments
+ const string kSegmentNum = HLS_FIELD"segNum";
+ //Number of HLS segments retained on disk after removal from m3u8 file
+ const string kSegmentRetain = HLS_FIELD"segRetain";
+ //HLS file write buffer size
+ const string kFileBufSize = HLS_FIELD"fileBufSize";
+ //Recording file path
+ const string kFilePath = HLS_FIELD"filePath";
+
+ onceToken token([](){
+ mINI::Instance()[kSegmentDuration] = 2;
+ mINI::Instance()[kSegmentNum] = 3;
+ mINI::Instance()[kSegmentRetain] = 5;
+ mINI::Instance()[kFileBufSize] = 64 * 1024;
+ mINI::Instance()[kFilePath] = "./www";
+ },nullptr);
+ } //namespace Hls
+ ```
2. Used as a static variable to ensure code execution only once:
- ```C++
- int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
- typedef void (HttpSession::*HttpCMDHandle)(int64_t &);
- static unordered_map s_func_map;
- static onceToken token([]() {
- s_func_map.emplace("GET",&HttpSession::Handle_Req_GET);
- s_func_map.emplace("POST",&HttpSession::Handle_Req_POST);
- }, nullptr);
-
- //Omitted subsequent code
- }
- ```
+
+ ```cpp
+ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
+ typedef void (HttpSession::*HttpCMDHandle)(int64_t &);
+ static unordered_map s_func_map;
+ static onceToken token([]() {
+ s_func_map.emplace("GET",&HttpSession::Handle_Req_GET);
+ s_func_map.emplace("POST",&HttpSession::Handle_Req_POST);
+ }, nullptr);
+
+ //Omitted subsequent code
+ }
+ ```
3. Used as a local variable to ensure some cleanup work before a function exits, such as releasing a lock:
- ```C++
- template
- bool emitEvent(const string &strEvent,ArgsType &&...args){
- onceToken token([&] {
- //Lock and record the locked thread ID
- _mtxListener.lock();
- if(_lock_depth++ == 0){
- _lock_thread = this_thread::get_id();
- }
- }, [&]() {
- //Release the lock and clear the locked thread ID
- if(--_lock_depth == 0){
- _lock_thread = thread::id();
- if(_map_moved){
- //Restore _mapListener
- _map_moved = false;
- _mapListener = std::move(_mapListenerTemp);
- }
- }
- _mtxListener.unlock();
- });
-
- //Omitted subsequent code
- }
- ```
+
+ ```cpp
+ template
+ bool emitEvent(const string &strEvent,ArgsType &&...args){
+ onceToken token([&] {
+ //Lock and record the locked thread ID
+ _mtxListener.lock();
+ if(_lock_depth++ == 0){
+ _lock_thread = this_thread::get_id();
+ }
+ }, [&]() {
+ //Release the lock and clear the locked thread ID
+ if(--_lock_depth == 0){
+ _lock_thread = thread::id();
+ if(_map_moved){
+ //Restore _mapListener
+ _map_moved = false;
+ _mapListener = std::move(_mapListenerTemp);
+ }
+ }
+ _mtxListener.unlock();
+ });
+
+ //Omitted subsequent code
+ }
+ ```
4. The name of this object is derived from `pthread_once` and `dispatch_once` in iOS.
diff --git a/src/guide/faq/not_recommended_qq.md b/src/guide/faq/not_recommended_qq.md
index 3534510..301f75e 100644
--- a/src/guide/faq/not_recommended_qq.md
+++ b/src/guide/faq/not_recommended_qq.md
@@ -1,6 +1,7 @@
---
title: Why is it not recommended to consult questions via QQ private chat?
---
+
## Why is private chat not recommended
1. Private chat on QQ is difficult to trace and organize, making it hard to form documentation. There are often repetitive questions, which do not benefit the project.
diff --git a/src/guide/install/compilation_instructions_for_windows_version.md b/src/guide/install/compilation_instructions_for_windows_version.md
index fe34510..2980ddd 100644
--- a/src/guide/install/compilation_instructions_for_windows_version.md
+++ b/src/guide/install/compilation_instructions_for_windows_version.md
@@ -20,27 +20,32 @@ The following steps are for installing the dependency tools `cmake` and `ninja`
For detailed instructions, please refer to the official scoop documentation. Below are the summarized steps:
1. Set the environment variable `SCOOP` to configure the download and installation directory for `scoop` (including the managed software packages). Run the following command:
- ```
+
+ ```sh
$env:SCOOP = 'C:\work\develop\scoop'
```
2. Allow the execution of PowerShell scripts for the current user by running the following command:
- ```
+
+ ```sh
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
3. Install `scoop` by running the following command:
- ```
+
+ ```sh
iwr -useb get.scoop.sh | iex
```
4. Add the `extras` software repository to `scoop` by running the following command:
- ```
+
+ ```sh
scoop bucket add extras
```
5. Install `cmake` and `ninja` by running the following command:
- ```
+
+ ```sh
scoop install cmake ninja
```
@@ -53,22 +58,26 @@ The following steps are for installing the required library dependencies, includ
For detailed usage of `vcpkg`, please refer to the [official documentation](https://github.com/microsoft/vcpkg).
1. Download `vcpkg`, which includes various configuration scripts and build scripts for open-source libraries. Assume the download path is `C:\work\develop`. Run the following command:
- ```
+
+ ```sh
git clone https://github.com/microsoft/vcpkg
```
2. Download the precompiled `vcpkg` package manager by running the following command:
- ```
+
+ ```sh
.\vcpkg\bootstrap-vcpkg.bat -disableMetrics
```
3. Build `openssl` by running the following command:
- ```
+
+ ```sh
.\vcpkg\vcpkg.exe install --triplet=x64-windows-static openssl
```
4. Build `libsrtp` with `ENABLE_OPENSSL` enabled. Edit `C:\work\develop\vcpkg\ports\libsrtp\portfile.cmake` and modify `vcpkg_configure_cmake` as follows:
- ```
+
+ ```cmake
vcpkg_configure_cmake(
SOURCE_PATH ${SOURCE_PATH}
PREFER_NINJA
@@ -78,7 +87,8 @@ For detailed usage of `vcpkg`, please refer to the [official documentation](http
```
Then, build `libsrtp` by running the following command:
- ```
+
+ ```sh
.\vcpkg\vcpkg.exe install --triplet=x64-windows-static libsrtp
```
diff --git a/src/guide/install/start.md b/src/guide/install/start.md
index 2924bd2..5f5b749 100644
--- a/src/guide/install/start.md
+++ b/src/guide/install/start.md
@@ -2,22 +2,22 @@
title: Start
order: 1
---
+
## 1. Obtain the Source Code
**Please refrain from downloading the source code in zip package format directly from GitHub**. Instead, you should clone the ZLMediaKit code using git. This is due to ZLMediaKit's reliance on multiple third-party project codes which are not included in the zip package. Follow these steps to do this:
- ```bash
- # It's recommended for users in China to download from the synchronized mirror site, gitee
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- # Remember to execute this command
- git submodule update --init
- ```
+```bash
+# It's recommended for users in China to download from the synchronized mirror site, gitee
+git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+cd ZLMediaKit
+# Remember to execute this command
+git submodule update --init
+```
## 2. Strongly Recommended
-If you're a beginner, we highly recommend compiling ZLMediaKit using Ubuntu16 or later versions. macOS is the second recommended platform. The least recommended platforms are CentOS6.* and Windows.
-
+If you're a beginner, we highly recommend compiling ZLMediaKit using Ubuntu16 or later versions. macOS is the second recommended platform. The least recommended platforms are CentOS6.\* and Windows.
zlmediakit has been launched on vcpkg, please refer to [install zlmediakit using vcpkg](install_zlmediakit_using_vcpkg.md) for convenient installation.
@@ -31,8 +31,6 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
- On macOS, clang >= ??? (it's uncertain, but most likely won't encounter any issues)
- On Windows, Visual Studio >= 2015 (some versions of VS2013 can also compile, but for a smoother experience, VS2017 is recommended)
-
-
### 3.2. Installing the Compiler
- If you're using a Debian-based operating system (including Ubuntu), the built-in gcc version is usually recent enough. Here's how to install the gcc compiler:
@@ -48,7 +46,7 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
sudo yum -y install gcc-c++
```
-- If you're a CentOS6.* user, you can install the gcc compiler this way:
+- If you're a CentOS6.\* user, you can install the gcc compiler this way:
```bash
sudo yum install centos-release-scl -y
@@ -61,8 +59,6 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
- If you're a Windows user, it's recommended to install VS2017 or later versions.
-
-
## 4. CMake
ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile (or Xcode/VS project), so you must install CMake to complete the subsequent steps.
@@ -79,7 +75,7 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
sudo yum -y install cmake
```
-- If you're a CentOS6.* user, then you need to download the new version of cmake source code and then compile and install cmake:
+- If you're a CentOS6.\* user, then you need to download the new version of cmake source code and then compile and install cmake:
```bash
wget https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3.tar.gz
@@ -90,8 +86,6 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
sudo make install
```
-
-
- If you're a macOS user, here's how you can install cmake:
```bash
@@ -103,12 +97,11 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
```bash
# Install win64 version of cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win64-x64.zip
-
+
# Install win32 version of cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win32-x86.zip
```
-
## 5. Dependencies
### 5.1 Dependency List
@@ -142,7 +135,7 @@ Most of the third-party libraries that ZLMediaKit depends on are optional. Durin
sudo apt-get install ffmpeg
```
-- Users of centos6.* can refer to this [article](https://blog.51cto.com/mengix/2452395).
+- Users of centos6.\* can refer to this [article](https://blog.51cto.com/mengix/2452395).
- To install dependencies on macOS/CentOS:
@@ -183,15 +176,15 @@ The activation of webrtc related features is complex and is not enabled for comp
```sh
1 Enter the ZLMediaKit directory and execute git submodule update --init to download the code of ZLToolKit
-
- 2 Use cmake-gui to open the project and generate the vs project file.
- 3 Locate the project file (ZLMediaKit.sln), double-click to open with vs2017.
- 4 Choose to compile the Release version.
- 5 Locate the target file and run the test case.
```
- - Also, you can refer to [here](compilation_instructions_for_windows_version.md) for Windows compilation.
+2 Use cmake-gui to open the project and generate the vs project file.
+3 Locate the project file (ZLMediaKit.sln), double-click to open with vs2017.
+4 Choose to compile the Release version.
+5 Locate the target file and run the test case.
+
+- Also, you can refer to [here](compilation_instructions_for_windows_version.md) for Windows compilation.
- If you want to compile the Android version, you can open the Android directory in Android Studio.
@@ -212,7 +205,7 @@ The ZLMediaKit project mainly generates three types of binary target files, whic
- MediaServer Process
This is the main process of ZLMediaKit as a server. This process can be used directly as a streaming media server for testing without any development. If you need more complex business logic, you can implement it through [Web HOOK](../media_server/web_hook_api.md) and [RESTful API](../media_server/restful_api.md). At the same time, you can control its parameters through the [configuration file](../media_server/config_file.md).
-
+
- Start on Linux:
```sh
@@ -226,7 +219,7 @@ The ZLMediaKit project mainly generates three types of binary target files, whic
- Start on macOS:
The target file directory is in ZLMediaKit/mac/Debug, and all other operations are the same.
-
+
- Start on Windows:
```sh
@@ -259,7 +252,7 @@ The ZLMediaKit project mainly generates three types of binary target files, whic
```
The SDK header file has detailed comments, which are generally sufficient for secondary development.
-
+
- Test programs starting with `test_`
The related code is in the `ZLMediaKit/tests` directory, and you can refer to the code to start the test process.
diff --git a/src/guide/media_server/README.md b/src/guide/media_server/README.md
index 1eb3983..a6ccc1d 100644
--- a/src/guide/media_server/README.md
+++ b/src/guide/media_server/README.md
@@ -15,6 +15,3 @@ tag:
- [Playing URL Rules](play_url_rules.md)
- [Starting and Stopping the Server](start_server.md)
-
-
-
diff --git a/src/guide/media_server/config_file.md b/src/guide/media_server/config_file.md
index 0d57e23..553a531 100644
--- a/src/guide/media_server/config_file.md
+++ b/src/guide/media_server/config_file.md
@@ -1,6 +1,7 @@
---
title: Configuration File Explanation
---
+
```ini
#!!!! This configuration file is an example configuration file intended to inform the reader about the specific meanings and functions of each configuration item.
#!!!! When executing cmake, this configuration file will be copied to the release/${operating_system_type}/${build_type} (e.g., release/linux/Debug) folder.
@@ -388,5 +389,5 @@ maxReqSize=1024
# Telnet server listening port in debug mode
port=0
```
-You can also refer to [HTTP-HOOK-API](web_hook_api.md) Supported by MediaServer for configuration related to hooks.
+You can also refer to [HTTP-HOOK-API](web_hook_api.md) Supported by MediaServer for configuration related to hooks.
diff --git a/src/guide/media_server/generate_ssl_self-signed_certificate_and_test.md b/src/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
index d8ee2c2..3130d38 100644
--- a/src/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
+++ b/src/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
@@ -1,16 +1,21 @@
---
title: Generate SSL self-signed certificate and test
---
+
# 1. Generate Private Key
+
```bash
openssl genrsa -out server.key 2048
```
# 2. Create Certificate Signing Request (CSR) File
+
```bash
openssl req -new -key server.key -out server.csr
```
+
Note: You will be prompted to enter the domain name (Common Name (e.g. server FQDN or YOUR name)):
+
```bash
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:gd
@@ -27,10 +32,13 @@ An optional company name []:zlm
```
# 3. Self-Sign the Certificate and Generate Public Key (Valid for 10 years)
+
```bash
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
```
+
Executing this command will print the following information:
+
```bash
Signature ok
subject=/C=cn/ST=gd/L=sz/O=company/OU=section/CN=zlm.com/emailAddress=xiachu@qq.com
@@ -38,15 +46,15 @@ Getting Private key
```
# 4. Merge Public Key and Private Key
+
```bash
cat server.crt server.key > ./ssl.pem
```
# 5. Load the Certificate
+
```bash
./MediaServer -s ./ssl.pem
```
-![图片.png](/images/generate_ssl_self-signed_certificate_and_test.webp)
-
-
+![图片.png](/images/generate_ssl_self-signed_certificate_and_test.webp)
diff --git a/src/guide/media_server/how_to_enable_https_related_functions.md b/src/guide/media_server/how_to_enable_https_related_functions.md
index 127548b..ab1445a 100644
--- a/src/guide/media_server/how_to_enable_https_related_functions.md
+++ b/src/guide/media_server/how_to_enable_https_related_functions.md
@@ -3,7 +3,9 @@ title: How to Enable HTTPS Related Functions
---
### I. Enable OpenSSL Feature during Compilation
+
The HTTPS feature of zlmediakit (including rtmps/rtsps/webrtc/wss) relies on the OpenSSL library. Before compiling zlmediakit, you should first install the OpenSSL library in the default system environment. On Ubuntu, you can install it using the following command:
+
```bash
sudo apt-get install libssl-dev
```
@@ -19,9 +21,10 @@ make -j$(nproc)
```
## II. Create Certificates
+
- If you haven't purchased a domain name yet, you can use a [self-signed certificate](./generate_ssl_self-signed_certificate_and_test.md) or the default certificate `default.pem` provided by zlmediakit for testing.
-- If you have already purchased a domain name, using Alibaba Cloud as an example, you can choose to apply for a free certificate for your domain:**
+- If you have already purchased a domain name, using Alibaba Cloud as an example, you can choose to apply for a free certificate for your domain:\*\*
![图片](/images/how_to_enable_https_related_functions_zh_1.png)
@@ -34,6 +37,7 @@ make -j$(nproc)
![图片](/images/how_to_enable_https_related_functions_zh_3.png)
## III. Download and Merge Certificates into the Supported Format by zlmediakit:
+
- **Download the certificates:**
![图片](/images/how_to_enable_https_related_functions_zh_4.png)
@@ -44,8 +48,7 @@ make -j$(nproc)
- **After extracting the downloaded compressed file, the files are as follows**:
-
-
+![图片](https://user-images.githubusercontent.com/11495632/191884186-3c09f0ed-0042-417c-a8dc-ad87c4c0c1ed.png =760x)
- The files with the ".key" extension are private keys, and the files with the ".pem" extension are public keys. Both can be opened with a text editor. They are base64-encoded strings. After concatenating the two strings together, you will get the certificate file format supported by zlmediakit:
@@ -71,8 +74,6 @@ cp ~/Downloads/8516590_test.zlmediakit.com_nginx/default.pem ./
![图片](/images/how_to_enable_https_related_functions_zh_6.png)
-
-
## V. Testing
- If the IP address of your development machine does not map to the IP address bound to the certificate domain, you can modify the host file to perform the test. Here is an example for Linux/Mac:
@@ -93,7 +94,6 @@ sudo vi /etc/hosts
![图片](/images/how_to_enable_https_related_functions_zh_8.png)
-
## VI. Deploying in a Production Environment
- After completing all the previous steps and passing the verification, you can proceed to deploy the application in a production environment. To do this, you need to bind the certificate domain name to the real public IP address of your cloud host:
@@ -101,10 +101,3 @@ sudo vi /etc/hosts
![图片](/images/how_to_enable_https_related_functions_zh_9.png)
![图片](/images/how_to_enable_https_related_functions_zh_10.png)
-
-
-
-
-
-
-
diff --git a/src/guide/media_server/on-demand_push_streaming.md b/src/guide/media_server/on-demand_push_streaming.md
index f7f9660..f825f2a 100644
--- a/src/guide/media_server/on-demand_push_streaming.md
+++ b/src/guide/media_server/on-demand_push_streaming.md
@@ -3,4 +3,5 @@ title: Implement on-demand push streaming
---
The MediaServer process of ZLMediaKit can be used to implement on-demand push streaming:
+
![image](/images/on-demand_push_streaming_zh.png)
diff --git a/src/guide/media_server/on-demand_streaming.md b/src/guide/media_server/on-demand_streaming.md
index 32d33da..eb3df27 100644
--- a/src/guide/media_server/on-demand_streaming.md
+++ b/src/guide/media_server/on-demand_streaming.md
@@ -1,7 +1,7 @@
---
title: Implement on-demand pull streaming
---
-The MediaServer process of ZLMediaKit can be used to implement on-demand pull streaming:
-![image](/images/on-demand_streaming_zh.png)
+The MediaServer process of ZLMediaKit can be used to implement on-demand pull streaming:
+![image](/images/on-demand_streaming_zh.png)
diff --git a/src/guide/media_server/play_url_rules.md b/src/guide/media_server/play_url_rules.md
index 1e74a07..d33aadd 100644
--- a/src/guide/media_server/play_url_rules.md
+++ b/src/guide/media_server/play_url_rules.md
@@ -4,7 +4,9 @@ icon: circle-info
---
## 1. Components of a URL
+
Taking `rtsp://somedomain.com:554/live/0?token=abcdefg&field=value` as an example, this URL is divided into the following parts:
+
- `Protocol(scheam)`: RTSP protocol, default port 554
- `Virtual Host(vhost)`: somedomain.com. This field can be either a domain name or an IP. If it is an IP, the corresponding virtual host is `__defaultVhost__`
- `Server Port(port)`: 554. If the port number is not specified, the protocol's default port number is used
@@ -13,9 +15,11 @@ Taking `rtsp://somedomain.com:554/live/0?token=abcdefg&field=value` as an exampl
- `Parameters(args)`: token=abcdefg&field=value
## 2. Stream Media Source in ZLMediaKit
+
In ZLMediaKit, a stream media source is a data object that can be used for functions such as live broadcasting and stream forwarding, and is referred to as `MediaSource` in this project. Currently, it supports five types of stream media sources, namely `RtspMediaSource`, `RtmpMediaSource`, `HlsMediaSource`, `TSMediaSource`, `FMP4MediaSource`.
Identifying a stream media source is mainly based on four elements (referred to as 4-tuples hereafter), which are:
+
- `Protocol(scheam)`
- `Virtual Host(vhost)`
- `Application Name(app)`
@@ -32,8 +36,10 @@ Identifying a stream media source is mainly based on four elements (referred to
`FMP4MediaSource` supports HTTP-FMP4 playback and WS-FMP4 playback.
## 3. Playback URLs Corresponding to the Stream Media Source
+
Suppose there is a `RtspMediaSource`, and its 4-tuple are `rtsp (RtspMediaSource is always rtsp)`, `somedomain.com`, `live`, and `0`
Then the URLs for playing this stream media source correspond to:
+
- `rtsp://somedomain.com/live/0`
- `rtsps://somedomain.com/live/0`
- `rtsp://127.0.0.1/live/0?vhost=somedomain.com`
@@ -41,6 +47,7 @@ Then the URLs for playing this stream media source correspond to:
If there is a `RtmpMediaSource`, and its 4-tuple are `rtmp (RtmpMediaSource is always rtmp)`, `somedomain.com`, `live`, and `0`
Then the URLs for playing this stream media source correspond to:
+
- `rtmp://somedomain.com/live/0`
- `rtmps://somedomain.com/live/0`
- `rtmp://127.0.0.1/live/0?vhost=somedomain.com`
@@ -49,6 +56,7 @@ Then the URLs for playing this stream media source correspond to:
RTMP types of stream media sources also support live streaming through `http-flv`, `websocket`, and other protocols. The corresponding URLs are as follows:
**Note: Old code live broadcast suffix is .flv, and it has been changed to .live.flv in the new code**
+
- `http://somedomain.com/live/0.live.flv`
- `https://somedomain.com/live/0.live.flv`
- `http://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
@@ -58,16 +66,17 @@ RTMP types of stream media sources also support live streaming through `http-flv
- `ws://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
- `wss://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
-
Sure, ZLMediaKit typically converts RTSP and RTMP media streams to each other and also transforms them into HLS/HTTP-TS/WS-TS/HTTP-fMP4/WS-fMP4. The playback URLs are as follows:
- HLS
+
- `http://somedomain.com/live/0/hls.m3u8`
- `https://somedomain.com/live/0/hls.m3u8`
- `http://127.0.0.1/live/0/hls.m3u8?vhost=somedomain.com`
- `https://127.0.0.1/live/0/hls.m3u8?vhost=somedomain.com`
- HTTP-TS/WS-TS (with the suffix .live.ts, to resolve the conflict with HLS)
+
- `http://somedomain.com/live/0.live.ts`
- `https://somedomain.com/live/0.live.ts`
- `http://127.0.0.1/live/0.live.ts?vhost=somedomain.com`
@@ -90,22 +99,24 @@ Sure, ZLMediaKit typically converts RTSP and RTMP media streams to each other an
Generally speaking, all the above URLs are valid in ZLMediaKit, as ZLMediaKit converts media sources by default.
## 4. Video-on-Demand URL
+
ZLMediaKit typically implements video-on-demand via MP4 files, and we recommend using HTTP MP4 on-demand as it is the simplest method and the server does not need to demultiplex the MP4 files. ZLMediaKit currently also supports RTSP, RTMP, HTTP-FLV, and WebSocket-FLV MP4 on-demand. The corresponding URLs are similar to live broadcast URLs and will not be elaborated here; only the differences are discussed.
- ZLMediaKit restricts the application name for on-demand to the default `record`.
- Suppose an MP4 file is placed in the HTTP root directory record folder (`www/record`). Its relative path is `www/record/0.mp4`, then the on-demand URL would be:
- - `rtsp://somedomain.com/record/0.mp4`
- - `rtmp://somedomain.com/record/0.mp4`
- - `http://somedomain.com/record/0.mp4` (This is a generic HTTP file on-demand; the server does not need to demultiplex the file)
- - `http://somedomain.com/record/0.mp4.live.flv` (This is HTTP-FLV live streaming, not HTTP on-demand; the server needs to demultiplex the file)
- - `ws://somedomain.com/record/0.mp4.live.flv`
- - `http://somedomain.com/record/0.mp4.live.ts` (This is HTTP-TS live streaming, not HTTP on-demand; the server needs to demultiplex the file)
- - `ws://somedomain.com/record/0.mp4.live.ts`
- - `http://somedomain.com/record/0.mp4.live.mp4` (This is HTTP-fMP4 live streaming, not HTTP on-demand; the server needs to demultiplex the file)
- - `ws://somedomain.com/record/0.mp4.live.mp4`
+ - `rtsp://somedomain.com/record/0.mp4`
+ - `rtmp://somedomain.com/record/0.mp4`
+ - `http://somedomain.com/record/0.mp4` (This is a generic HTTP file on-demand; the server does not need to demultiplex the file)
+ - `http://somedomain.com/record/0.mp4.live.flv` (This is HTTP-FLV live streaming, not HTTP on-demand; the server needs to demultiplex the file)
+ - `ws://somedomain.com/record/0.mp4.live.flv`
+ - `http://somedomain.com/record/0.mp4.live.ts` (This is HTTP-TS live streaming, not HTTP on-demand; the server needs to demultiplex the file)
+ - `ws://somedomain.com/record/0.mp4.live.ts`
+ - `http://somedomain.com/record/0.mp4.live.mp4` (This is HTTP-fMP4 live streaming, not HTTP on-demand; the server needs to demultiplex the file)
+ - `ws://somedomain.com/record/0.mp4.live.mp4`
- If virtual hosting is enabled, then the on-demand files should be placed in `www/somedomain.com/record/0.mp4`.
## 5. WebRTC Push/Pull
+
WebRTC playback is slightly different from the methods mentioned above. The WebRTC protocol itself does not define a signaling interaction protocol, and users need to implement the `sdp+icecandidate` exchange logic themselves. So, WebRTC does not have a standard player, and you need to use JS or a native SDK to implement playback.
ZLMediaKit implements the `WebRTC SDP+icecandidate` exchange method via `HTTP POST`. The interface name is `/index/api/webrtc`. This interface uses POST content to pass the `offer sdp` while passing the media source's four-tuple `app` `stream_id` in the URL query parameters. Since HTTP inherently supports `vhost`, there's no need to specify `vhost` separately. WebRTC in ZLMediaKit can be considered another representation of the RTSP protocol. Their push and playback use the same data source, which is `RtspMediaSource`.
@@ -119,4 +130,5 @@ ZLMediaKit comes with a WebRTC test player/pusher. After starting ZLMediaKit, yo
Additionally, ZLMediaKit also supports playing MP4 files via WebRTC. The HTTP POST interface is similar to: `http://127.0.0.1/index/api/webrtc?app=record&stream=test.mp4&type=play`.
## 6. URL Parameters
+
ZLMediaKit recognizes the string after the question mark in the URL as parameters, which are consistent with HTTP formats. Among them, `vhost` is a built-in parameter supported by ZLMediaKit, which allows specifying a virtual host. URL parameters are mainly used for streaming and playback authentication. When triggering the hook API, these parameters will be submitted to the third-party business server.
diff --git a/src/guide/media_server/playback_authentication.md b/src/guide/media_server/playback_authentication.md
index da878e4..923fd1b 100644
--- a/src/guide/media_server/playback_authentication.md
+++ b/src/guide/media_server/playback_authentication.md
@@ -1,6 +1,7 @@
---
title: Implementing Playback Authentication
---
+
The MediaServer process of ZLMediaKit can be used to implement playback authentication:
-![image](/images/playback_authentication_zh.png)
+![image](/images/playback_authentication_zh.png)
diff --git a/src/guide/media_server/push_authentication.md b/src/guide/media_server/push_authentication.md
index 726c124..937b744 100644
--- a/src/guide/media_server/push_authentication.md
+++ b/src/guide/media_server/push_authentication.md
@@ -1,7 +1,7 @@
---
title: Implementing Push Streaming Authentication
---
-The MediaServer process of ZLMediaKit can be used to implement push authentication:
-![image](/images/push_authentication_zh.png)
+The MediaServer process of ZLMediaKit can be used to implement push authentication:
+![image](/images/push_authentication_zh.png)
diff --git a/src/guide/media_server/push_test.md b/src/guide/media_server/push_test.md
index e2506fa..2bd5d35 100644
--- a/src/guide/media_server/push_test.md
+++ b/src/guide/media_server/push_test.md
@@ -1,36 +1,45 @@
---
title: Push and Playback Testing
---
+
## Push Testing
+
ZLMediaKit supports RTSP/RTMP/RTP push streaming. Typically, OBS/FFmpeg is used for push testing. The FFmpeg push commands are as follows:
1. Pushing via RTSP:
- ```bash
- # H.264 push
- ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
- # H.265 push
- ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
- ```
+
+ ```bash
+ # H.264 push
+ ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
+ # H.265 push
+ ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
+ ```
+
2. Pushing via RTMP:
- ```bash
- # If FFmpeg is not installed, you can also use OBS for push streaming
- ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f flv rtmp://127.0.0.1/live/test
- # The RTMP standard does not support H.265, but there are domestic extensions. If you want FFmpeg to support RTMP-H.265, please follow the instructions in this article to compile: https://github.com/ksvc/FFmpeg/wiki/hevcpush
- ```
+
+ ```bash
+ # If FFmpeg is not installed, you can also use OBS for push streaming
+ ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f flv rtmp://127.0.0.1/live/test
+ # The RTMP standard does not support H.265, but there are domestic extensions. If you want FFmpeg to support RTMP-H.265, please follow the instructions in this article to compile: https://github.com/ksvc/FFmpeg/wiki/hevcpush
+ ```
3. Pushing via RTP:
-```bash
-# H.264 push
-ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
-# H.265 push
-ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
-```
+
+ ```bash
+ # H.264 push
+ ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
+ # H.265 push
+ ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
+ ```
## Log Observation
+
If the push is successful, the following log will be printed:
+
![image](/images/push_test.png)
The relevant strings in the log represent:
+
```bash
2020-04-10 12:51:52.331 I | regist rtsp __defaultVhost__ rtp 206442D7
^ ^ ^ ^
@@ -38,6 +47,5 @@ The relevant strings in the log represent:
```
## Playback URL
-Please refer to the [play URL rules](./play_url_rules.md) to play the aforementioned push stream.
-
+Please refer to the [play URL rules](./play_url_rules.md) to play the aforementioned push stream.
diff --git a/src/guide/media_server/restful_api.md b/src/guide/media_server/restful_api.md
index f4e4755..6ff2c9e 100644
--- a/src/guide/media_server/restful_api.md
+++ b/src/guide/media_server/restful_api.md
@@ -51,8 +51,6 @@ MediaServer is the main process of ZLMediaKit and currently supports the followi
For the POST method, parameters can be sent in either urlencoded or JSON format. To authenticate these API operations, the `secret` parameter needs to be provided. However, if the operation is performed from the IP address 127.0.0.1, authentication is not required.
-
-
## API Response Conventions
- At the HTTP level, a unified 200 status code is returned, and the response body is always in JSON format.
@@ -60,14 +58,14 @@ For the POST method, parameters can be sent in either urlencoded or JSON format.
```json
{
- "code" : -1,
- "msg" : "Failure message"
+ "code": -1,
+ "msg": "Failure message"
}
```
- The `code` field represents the execution result and can have the following values:
-```c++
+```cpp
typedef enum {
Exception = -400, // Exception in the code
InvalidArgs = -300, // Invalid parameters
@@ -82,12 +80,11 @@ typedef enum {
- When `code == -1`, it indicates that the business code execution was unsuccessful. More specific reasons are usually provided in the `result` field, as shown below:
-
```json
{
- "code" : -1, // Business code execution failed
- "msg" : "can not find the stream", // Failure message
- "result" : -2 // Specific reason for business code execution failure
+ "code": -1, // Business code execution failed
+ "msg": "can not find the stream", // Failure message
+ "result": -2 // Specific reason for business code execution failure
}
```
@@ -107,621 +104,589 @@ typedef enum {
- Response:
- ```json
- {
- "code": 0,
- "data": [
- "/index/",
- "/index/api/addFFmpegSource",
- "/index/api/addStreamProxy",
- "/index/api/addStreamPusherProxy",
- "/index/api/closeRtpServer",
- "/index/api/close_stream",
- "/index/api/delFFmpegSource",
- "/index/api/delStreamProxy",
- "/index/api/delStreamPusherProxy",
- "/index/api/downloadBin",
- "/index/api/getAllSession",
- "/index/api/getApiList",
- "/index/api/getMediaInfo",
- "/index/api/getMediaList",
- "/index/api/getMp4RecordFile",
- "/index/api/getRtpInfo",
- "/index/api/getServerConfig",
- "/index/api/getSnap",
- "/index/api/getStatistic",
- "/index/api/getThreadsLoad",
- "/index/api/getWorkThreadsLoad",
- "/index/api/isMediaOnline",
- "/index/api/isRecording",
- "/index/api/kick_session",
- "/index/api/kick_sessions",
- "/index/api/listRtpServer",
- "/index/api/openRtpServer",
- "/index/api/pauseRtpCheck",
- "/index/api/restartServer",
- "/index/api/resumeRtpCheck",
- "/index/api/setServerConfig",
- "/index/api/startRecord",
- "/index/api/startSendRtp",
- "/index/api/stopRecord",
- "/index/api/stopSendRtp",
- "/index/api/version",
- "/index/api/webrtc",
- "/index/hook/on_flow_report",
- "/index/hook/on_http_access",
- "/index/hook/on_play",
- "/index/hook/on_publish",
- "/index/hook/on_record_hls",
- "/index/hook/on_record_mp4",
- "/index/hook/on_rtsp_auth",
- "/index/hook/on_rtsp_realm",
- "/index/hook/on_server_started",
- "/index/hook/on_shell_login",
- "/index/hook/on_stream_changed",
- "/index/hook/on_stream_none_reader",
- "/index/hook/on_stream_not_found",
- "/index/hook/on_stream_not_found_ffmpeg"
- ]
- }
- ```
-
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ "/index/",
+ "/index/api/addFFmpegSource",
+ "/index/api/addStreamProxy",
+ "/index/api/addStreamPusherProxy",
+ "/index/api/closeRtpServer",
+ "/index/api/close_stream",
+ "/index/api/delFFmpegSource",
+ "/index/api/delStreamProxy",
+ "/index/api/delStreamPusherProxy",
+ "/index/api/downloadBin",
+ "/index/api/getAllSession",
+ "/index/api/getApiList",
+ "/index/api/getMediaInfo",
+ "/index/api/getMediaList",
+ "/index/api/getMp4RecordFile",
+ "/index/api/getRtpInfo",
+ "/index/api/getServerConfig",
+ "/index/api/getSnap",
+ "/index/api/getStatistic",
+ "/index/api/getThreadsLoad",
+ "/index/api/getWorkThreadsLoad",
+ "/index/api/isMediaOnline",
+ "/index/api/isRecording",
+ "/index/api/kick_session",
+ "/index/api/kick_sessions",
+ "/index/api/listRtpServer",
+ "/index/api/openRtpServer",
+ "/index/api/pauseRtpCheck",
+ "/index/api/restartServer",
+ "/index/api/resumeRtpCheck",
+ "/index/api/setServerConfig",
+ "/index/api/startRecord",
+ "/index/api/startSendRtp",
+ "/index/api/stopRecord",
+ "/index/api/stopSendRtp",
+ "/index/api/version",
+ "/index/api/webrtc",
+ "/index/hook/on_flow_report",
+ "/index/hook/on_http_access",
+ "/index/hook/on_play",
+ "/index/hook/on_publish",
+ "/index/hook/on_record_hls",
+ "/index/hook/on_record_mp4",
+ "/index/hook/on_rtsp_auth",
+ "/index/hook/on_rtsp_realm",
+ "/index/hook/on_server_started",
+ "/index/hook/on_shell_login",
+ "/index/hook/on_stream_changed",
+ "/index/hook/on_stream_none_reader",
+ "/index/hook/on_stream_not_found",
+ "/index/hook/on_stream_not_found_ffmpeg"
+ ]
+ }
+ ```
### 1. `/index/api/getThreadsLoad`
- - Function: Get the load and delay of each epoll (or select) thread.
+- Function: Get the load and delay of each epoll (or select) thread.
- - Example:[http://127.0.0.1/index/api/getThreadsLoad](http://127.0.0.1/index/api/getThreadsLoad)
+- Example:[http://127.0.0.1/index/api/getThreadsLoad](http://127.0.0.1/index/api/getThreadsLoad)
- - Parameters: None
+- Parameters: None
- - Response:
-
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "delay" : 0, // Delay of the thread
- "load" : 0 // Load of the thread, ranging from 0 to 100
- },
- {
- "delay" : 0,
- "load" : 0
- }
- ]
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ {
+ "delay": 0, // Delay of the thread
+ "load": 0 // Load of the thread, ranging from 0 to 100
+ },
+ {
+ "delay": 0,
+ "load": 0
+ }
+ ]
+ }
+ ```
### 2. `/index/api/getWorkThreadsLoad`
- - Function: Get the load and delay of each background epoll (or select) thread.
-
- - Example:[http://127.0.0.1/index/api/getWorkThreadsLoad](http://127.0.0.1/index/api/getWorkThreadsLoad)
+- Function: Get the load and delay of each background epoll (or select) thread.
- - Parameters: None
+- Example:[http://127.0.0.1/index/api/getWorkThreadsLoad](http://127.0.0.1/index/api/getWorkThreadsLoad)
- - Response:
+- Parameters: None
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "delay" : 0, // Delay of the thread
- "load" : 0 // Load of the thread, ranging from 0 to 100
- },
- {
- "delay" : 0,
- "load" : 0
- }
- ]
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ {
+ "delay": 0, // Delay of the thread
+ "load": 0 // Load of the thread, ranging from 0 to 100
+ },
+ {
+ "delay": 0,
+ "load": 0
+ }
+ ]
+ }
+ ```
### 3. `/index/api/getServerConfig`
- - Function: Get server configuration.
+- Function: Get server configuration.
- - Example:[http://127.0.0.1/index/api/getServerConfig](http://127.0.0.1/index/api/getServerConfig)
+- Example:[http://127.0.0.1/index/api/getServerConfig](http://127.0.0.1/index/api/getServerConfig)
- - Parameters:
-
- | Parameter | Required | Description |
- | :-------: | :------: | :-----------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
+- Parameters:
- - Response:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :----------------------------------------: |
+ | secret | Y | API operation key (configured in the file) |
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "api.apiDebug" : "1",
- "api.secret" : "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
- "ffmpeg.bin" : "/usr/local/bin/ffmpeg",
- "ffmpeg.cmd" : "%s -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s",
- "ffmpeg.log" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/ffmpeg/ffmpeg.log",
- "general.enableVhost" : "1",
- "general.flowThreshold" : "1024",
- "general.maxStreamWaitMS" : "5000",
- "general.streamNoneReaderDelayMS" : "5000",
- "hls.fileBufSize" : "65536",
- "hls.filePath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "hls.segDur" : "3",
- "hls.segNum" : "3",
- "hook.access_file_except_hls" : "1",
- "hook.admin_params" : "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc",
- "hook.enable" : "1",
- "hook.on_flow_report" : "https://127.0.0.1/index/hook/on_flow_report",
- "hook.on_http_access" : "https://127.0.0.1/index/hook/on_http_access",
- "hook.on_play" : "https://127.0.0.1/index/hook/on_play",
- "hook.on_publish" : "https://127.0.0.1/index/hook/on_publish",
- "hook.on_record_mp4" : "https://127.0.0.1/index/hook/on_record_mp4",
- "hook.on_rtsp_auth" : "https://127.0.0.1/index/hook/on_rtsp_auth",
- "hook.on_rtsp_realm" : "https://127.0.0.1/index/hook/on_rtsp_realm",
- "hook.on_shell_login" : "https://127.0.0.1/index/hook/on_shell_login",
- "hook.on_stream_changed" : "https://127.0.0.1/index/hook/on_stream_changed",
- "hook.on_stream_none_reader" : "https://127.0.0.1/index/hook/on_stream_none_reader",
- "hook.on_stream_not_found" : "https://127.0.0.1/index/hook/on_stream_not_found",
- "hook.timeoutSec" : "10",
- "http.charSet" : "utf-8",
- "http.keepAliveSecond" : "100",
- "http.maxReqCount" : "100",
- "http.maxReqSize" : "4096",
- "http.notFound" : "404 Not Found您访问的资源不存在!
ZLMediaKit-4.0",
- "http.port" : "80",
- "http.rootPath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "http.sendBufSize" : "65536",
- "http.sslport" : "443",
- "multicast.addrMax" : "239.255.255.255",
- "multicast.addrMin" : "239.0.0.0",
- "multicast.udpTTL" : "64",
- "record.appName" : "record",
- "record.filePath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "record.fileSecond" : "3600",
- "record.sampleMS" : "100",
- "rtmp.handshakeSecond" : "15",
- "rtmp.keepAliveSecond" : "15",
- "rtmp.modifyStamp" : "1",
- "rtmp.port" : "1935",
- "rtp.audioMtuSize" : "600",
- "rtp.clearCount" : "10",
- "rtp.cycleMS" : "46800000",
- "rtp.maxRtpCount" : "50",
- "rtp.videoMtuSize" : "1400",
- "rtsp.authBasic" : "0",
- "rtsp.handshakeSecond" : "15",
- "rtsp.keepAliveSecond" : "15",
- "rtsp.port" : "554",
- "rtsp.sslport" : "322",
- "shell.maxReqSize" : "1024",
- "shell.port" : "9000"
- }
- ]
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ {
+ "api.apiDebug": "1",
+ "api.secret": "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
+ "ffmpeg.bin": "/usr/local/bin/ffmpeg",
+ "ffmpeg.cmd": "%s -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s",
+ "ffmpeg.log": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/ffmpeg/ffmpeg.log",
+ "general.enableVhost": "1",
+ "general.flowThreshold": "1024",
+ "general.maxStreamWaitMS": "5000",
+ "general.streamNoneReaderDelayMS": "5000",
+ "hls.fileBufSize": "65536",
+ "hls.filePath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "hls.segDur": "3",
+ "hls.segNum": "3",
+ "hook.access_file_except_hls": "1",
+ "hook.admin_params": "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc",
+ "hook.enable": "1",
+ "hook.on_flow_report": "https://127.0.0.1/index/hook/on_flow_report",
+ "hook.on_http_access": "https://127.0.0.1/index/hook/on_http_access",
+ "hook.on_play": "https://127.0.0.1/index/hook/on_play",
+ "hook.on_publish": "https://127.0.0.1/index/hook/on_publish",
+ "hook.on_record_mp4": "https://127.0.0.1/index/hook/on_record_mp4",
+ "hook.on_rtsp_auth": "https://127.0.0.1/index/hook/on_rtsp_auth",
+ "hook.on_rtsp_realm": "https://127.0.0.1/index/hook/on_rtsp_realm",
+ "hook.on_shell_login": "https://127.0.0.1/index/hook/on_shell_login",
+ "hook.on_stream_changed": "https://127.0.0.1/index/hook/on_stream_changed",
+ "hook.on_stream_none_reader": "https://127.0.0.1/index/hook/on_stream_none_reader",
+ "hook.on_stream_not_found": "https://127.0.0.1/index/hook/on_stream_not_found",
+ "hook.timeoutSec": "10",
+ "http.charSet": "utf-8",
+ "http.keepAliveSecond": "100",
+ "http.maxReqCount": "100",
+ "http.maxReqSize": "4096",
+ "http.notFound": "404 Not Found您访问的资源不存在!
ZLMediaKit-4.0",
+ "http.port": "80",
+ "http.rootPath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "http.sendBufSize": "65536",
+ "http.sslport": "443",
+ "multicast.addrMax": "239.255.255.255",
+ "multicast.addrMin": "239.0.0.0",
+ "multicast.udpTTL": "64",
+ "record.appName": "record",
+ "record.filePath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "record.fileSecond": "3600",
+ "record.sampleMS": "100",
+ "rtmp.handshakeSecond": "15",
+ "rtmp.keepAliveSecond": "15",
+ "rtmp.modifyStamp": "1",
+ "rtmp.port": "1935",
+ "rtp.audioMtuSize": "600",
+ "rtp.clearCount": "10",
+ "rtp.cycleMS": "46800000",
+ "rtp.maxRtpCount": "50",
+ "rtp.videoMtuSize": "1400",
+ "rtsp.authBasic": "0",
+ "rtsp.handshakeSecond": "15",
+ "rtsp.keepAliveSecond": "15",
+ "rtsp.port": "554",
+ "rtsp.sslport": "322",
+ "shell.maxReqSize": "1024",
+ "shell.port": "9000"
+ }
+ ]
+ }
+ ```
### 4. `/index/api/setServerConfig`
- - Function: Set server configuration.
-
- - Example:[http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0(例如关闭http api调试)](http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0)
+- Function: Set server configuration.
- - Parameters:
+- Example:[http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0(例如关闭 http api 调试)](http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0)
- | Parameter | Required | Description |
- | :-------: | :------: | :-----------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
-
- - Response:
+- Parameters:
- ```json
- {
- "changed" : 0, // Number of configuration items changed
- "code" : 0 // 0 represents success
- }
- ```
+ | Parameter | Required | Description |
+ | :-------: | :------: | :----------------------------------------: |
+ | secret | Y | API operation key (configured in the file) |
+- Response:
+ ```json
+ {
+ "changed": 0, // Number of configuration items changed
+ "code": 0 // 0 represents success
+ }
+ ```
### 5. `/index/api/restartServer`
- - Function:Restart the server. Only possible in Daemon mode, otherwise it will be shut down directly!
+- Function:Restart the server. Only possible in Daemon mode, otherwise it will be shut down directly!
- - Example:[http://127.0.0.1/index/api/restartServer](http://127.0.0.1/index/api/restartServer)
+- Example:[http://127.0.0.1/index/api/restartServer](http://127.0.0.1/index/api/restartServer)
- - Parameters:
-
- | Parameter | Required | Description |
- | :-------: | :------: | :--------------------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
-
- - Response:
-
- ```json
- {
- "code" : 0,
- "msg" : "The server will automatically restart in one second."
- }
- ```
+- Parameters:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :----------------------------------------: |
+ | secret | Y | API operation key (configured in the file) |
+- Response:
+ ```json
+ {
+ "code": 0,
+ "msg": "The server will automatically restart in one second."
+ }
+ ```
### 6. `/index/api/getMediaList`
- - Function:Get the list of streams, with optional filtering parameters.
+- Function:Get the list of streams, with optional filtering parameters.
- - Example:[http://127.0.0.1/index/api/getMediaList](http://127.0.0.1/index/api/getMediaList)
+- Example:[http://127.0.0.1/index/api/getMediaList](http://127.0.0.1/index/api/getMediaList)
- - Parameters:
+- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :--------------------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
- | schema | N | Filter by protocol, e.g., rtsp or rtmp |
- | vhost | N | Filter by virtual host, e.g., `__defaultVhost__` |
- | app | N | Filter by application name, e.g., live |
- | stream | N | Filter by stream ID, e.g., test |
+ | Parameter | Required | Description |
+ | :-------: | :------: | :----------------------------------------------: |
+ | secret | Y | API operation key (configured in the file) |
+ | schema | N | Filter by protocol, e.g., rtsp or rtmp |
+ | vhost | N | Filter by virtual host, e.g., `__defaultVhost__` |
+ | app | N | Filter by application name, e.g., live |
+ | stream | N | Filter by stream ID, e.g., test |
- - Response:
+- Response:
- ```json
+ ```json
+ {
+ "code" : 0,
+ "data" : [
{
- "code" : 0,
- "data" : [
- {
- "app" : "live", # Application name
- "readerCount" : 0, # Number of viewers for this protocol
- "totalReaderCount" : 0, # Total number of viewers, including hls/rtsp/rtmp/http-flv/ws-flv
- "schema" : "rtsp", # Protocol
- "stream" : "obs", # Stream ID
- "originSock": { # Client and server network information, may be null
- "identifier": "140241931428384",
- "local_ip": "127.0.0.1",
- "local_port": 1935,
- "peer_ip": "127.0.0.1",
- "peer_port": 50097
- },
- "originType": 1, # Source type: unknown = 0, rtmp_push = 1, rtsp_push = 2, rtp_push = 3, pull = 4, ffmpeg_pull = 5, mp4_vod = 6, device_chn = 7
- "originTypeStr": "MediaOriginType::rtmp_push",
- "originUrl": "rtmp://127.0.0.1:1935/live/hks2", # URL of the source
- "createStamp": 1602205811, # GMT Unix system timestamp in seconds
- "aliveSecond": 100, # The time the stream remains alive, in seconds
- "bytesSpeed": 12345, # Data generation speed in bytes/s
- "tracks" : [ # Audio and video tracks
- {
- "channels" : 1, # Number of audio channels
- "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # Codec type name
- "codec_type" : 1, # Video = 0, Audio = 1
- "ready" : true, # Whether the track is ready
- "frames" : 1119, # Accumulated received frames
- "sample_bit" : 16, # Audio sample bit depth
- "sample_rate" : 8000 # Audio sample rate
- },
- {
- "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # Codec type name
- "codec_type" : 0, # Video = 0, Audio = 1
- "fps" : 59, # Video frames per second
- "frames" : 1119, # Accumulated received frames, excluding sei/aud/sps/pps frames that cannot be decoded
- "gop_interval_ms" : 1993, # GOP interval in milliseconds
- "gop_size" : 60, # gop size, unit number of frames
- "key_frames" : 21, # Accumulated received key frames
- "height" : 720, # video high
- "ready" : true, # Is the track ready?
- "width" : 1280 # video width
- }
- ],
- "vhost" : "__defaultVhost__" # Virtual host name
- }
- ]
- }
- ```
-
-
+ "app" : "live", # Application name
+ "readerCount" : 0, # Number of viewers for this protocol
+ "totalReaderCount" : 0, # Total number of viewers, including hls/rtsp/rtmp/http-flv/ws-flv
+ "schema" : "rtsp", # Protocol
+ "stream" : "obs", # Stream ID
+ "originSock": { # Client and server network information, may be null
+ "identifier": "140241931428384",
+ "local_ip": "127.0.0.1",
+ "local_port": 1935,
+ "peer_ip": "127.0.0.1",
+ "peer_port": 50097
+ },
+ "originType": 1, # Source type: unknown = 0, rtmp_push = 1, rtsp_push = 2, rtp_push = 3, pull = 4, ffmpeg_pull = 5, mp4_vod = 6, device_chn = 7
+ "originTypeStr": "MediaOriginType::rtmp_push",
+ "originUrl": "rtmp://127.0.0.1:1935/live/hks2", # URL of the source
+ "createStamp": 1602205811, # GMT Unix system timestamp in seconds
+ "aliveSecond": 100, # The time the stream remains alive, in seconds
+ "bytesSpeed": 12345, # Data generation speed in bytes/s
+ "tracks" : [ # Audio and video tracks
+ {
+ "channels" : 1, # Number of audio channels
+ "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecAAC", # Codec type name
+ "codec_type" : 1, # Video = 0, Audio = 1
+ "ready" : true, # Whether the track is ready
+ "frames" : 1119, # Accumulated received frames
+ "sample_bit" : 16, # Audio sample bit depth
+ "sample_rate" : 8000 # Audio sample rate
+ },
+ {
+ "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecH264", # Codec type name
+ "codec_type" : 0, # Video = 0, Audio = 1
+ "fps" : 59, # Video frames per second
+ "frames" : 1119, # Accumulated received frames, excluding sei/aud/sps/pps frames that cannot be decoded
+ "gop_interval_ms" : 1993, # GOP interval in milliseconds
+ "gop_size" : 60, # gop size, unit number of frames
+ "key_frames" : 21, # Accumulated received key frames
+ "height" : 720, # video high
+ "ready" : true, # Is the track ready?
+ "width" : 1280 # video width
+ }
+ ],
+ "vhost" : "__defaultVhost__" # Virtual host name
+ }
+ ]
+ }
+ ```
### 7. `/index/api/close_stream`(Deprecated, please use the `close_streams` API instead)
- - Function: Close a stream (supports closing streams of all types).
+- Function: Close a stream (supports closing streams of all types).
- - Example:[http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
+- Example:[http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
- - Parameters:
+- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :-------------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | schema | Y | Protocol, e.g., rtsp or rtmp |
- | vhost | Y | Virtual host, e.g., `__defaultVhost__` |
- | app | Y | Application name, e.g., live |
- | stream | Y | Stream ID, e.g., test |
- | force | N | Whether to force close (even if someone is watching) |
+ | Parameter | Required | Description |
+ | :-------: | :------: | :--------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | schema | Y | Protocol, e.g., rtsp or rtmp |
+ | vhost | Y | Virtual host, e.g., `__defaultVhost__` |
+ | app | Y | Application name, e.g., live |
+ | stream | Y | Stream ID, e.g., test |
+ | force | N | Whether to force close (even if someone is watching) |
- - Response:
+- Response:
- ```json
- {
- "code" : 0,
- "result" : 0, # 0: success, -1: failed to close, -2: stream does not exist
- "msg" : "success"
- }
- ```
+ ```json
+ {
+ "code" : 0,
+ "result" : 0, # 0: success, -1: failed to close, -2: stream does not exist
+ "msg" : "success"
+ }
+ ```
### 8. `/index/api/close_streams`
- - Function: Close a stream (supports closing streams of all types).
+- Function: Close a stream (supports closing streams of all types).
- - Example:[http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
+- Example:[http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
- - Parameters:
+- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :-------------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | schema | N | Protocol, e.g., rtsp or rtmp |
- | vhost | N | Virtual host, e.g., `__defaultVhost__` |
- | app | N | Application name, e.g., live |
- | stream | N | Stream ID, e.g., test |
- | force | N | Whether to force close (even if someone is watching) |
+ | Parameter | Required | Description |
+ | :-------: | :------: | :--------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | schema | N | Protocol, e.g., rtsp or rtmp |
+ | vhost | N | Virtual host, e.g., `__defaultVhost__` |
+ | app | N | Application name, e.g., live |
+ | stream | N | Stream ID, e.g., test |
+ | force | N | Whether to force close (even if someone is watching) |
- - Response:
+- Response:
- ```json
- {
- "code" : 0,
- "count_hit" : 1, # Number of streams hit by the filter
- "count_closed" : 1 # Number of streams closed, which may be less than count_hit
- }
- ```
+ ```json
+ {
+ "code" : 0,
+ "count_hit" : 1, # Number of streams hit by the filter
+ "count_closed" : 1 # Number of streams closed, which may be less than count_hit
+ }
+ ```
### 9. `/index/api/getAllSession`
- - Function: Get a list of all TcpSessions (retrieve information about all TCP clients).
-
- - Example:[http://127.0.0.1/index/api/getAllSession](http://127.0.0.1/index/api/getAllSession)
+- Function: Get a list of all TcpSessions (retrieve information about all TCP clients).
- - Parameters:
+- Example:[http://127.0.0.1/index/api/getAllSession](http://127.0.0.1/index/api/getAllSession)
- | Parameter | Required | Description |
- | :-----------: | :------: | :-------------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | local_port | N | Filter by local port, e.g., 554 |
- | peer_ip | N | Filter by client IP |
+- Parameters:
- - Response:
+ | Parameter | Required | Description |
+ | :--------: | :------: | :-----------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | local_port | N | Filter by local port, e.g., 554 |
+ | peer_ip | N | Filter by client IP |
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "id" : "140614477848784",
- "local_ip" : "127.0.0.1",
- "local_port" : 80,
- "peer_ip" : "127.0.0.1",
- "peer_port" : 51136,
- "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
- },
- {
- "id" : "140614443300192",
- "local_ip" : "127.0.0.1",
- "local_port" : 80,
- "peer_ip" : "127.0.0.1",
- "peer_port" : 51135,
- "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
- },
- {
- "id" : "140614440178720", # Unique ID for this TCP connection
- "local_ip" : "127.0.0.1", # Local IP address
- "local_port" : 1935, # Local port number (this is an RTMP player or publisher)
- "peer_ip" : "127.0.0.1", # Client IP address
- "peer_port" : 51130, # Client port number
- "typeid" : "N8mediakit11RtmpSessionE" # Client TCPSession typeid
- }
- ]
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "id" : "140614477848784",
+ "local_ip" : "127.0.0.1",
+ "local_port" : 80,
+ "peer_ip" : "127.0.0.1",
+ "peer_port" : 51136,
+ "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
+ },
+ {
+ "id" : "140614443300192",
+ "local_ip" : "127.0.0.1",
+ "local_port" : 80,
+ "peer_ip" : "127.0.0.1",
+ "peer_port" : 51135,
+ "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
+ },
+ {
+ "id" : "140614440178720", # Unique ID for this TCP connection
+ "local_ip" : "127.0.0.1", # Local IP address
+ "local_port" : 1935, # Local port number (this is an RTMP player or publisher)
+ "peer_ip" : "127.0.0.1", # Client IP address
+ "peer_port" : 51130, # Client port number
+ "typeid" : "N8mediakit11RtmpSessionE" # Client TCPSession typeid
+ }
+ ]
+ }
+ ```
### 10. `/index/api/kick_session`
- - Function: Disconnects a TCP connection, such as an RTSP or RTMP player.
-
- - Example:[http://127.0.0.1/index/api/kick_session?id=140614440178720](http://127.0.0.1/index/api/kick_session?id=140614440178720)
+- Function: Disconnects a TCP connection, such as an RTSP or RTMP player.
- - Parameters:
-
- | Parameter | Required | Description |
- | :-------: | :------: | :-------------------------------------------------------: |
- | secret | Y | API operation key (configured in the configuration file) |
- | Id | Y | Unique client ID, which can be obtained through the `getAllSession` interface |
+- Example:[http://127.0.0.1/index/api/kick_session?id=140614440178720](http://127.0.0.1/index/api/kick_session?id=140614440178720)
+- Parameters:
- - Response:
+| Parameter | Required | Description |
+| :-------: | :------: | :---------------------------------------------------------------------------: |
+| secret | Y | API operation key (configured in the configuration file) |
+| Id | Y | Unique client ID, which can be obtained through the `getAllSession` interface |
- ```json
- {
- "code" : 0,
- "msg" : "success"
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code": 0,
+ "msg": "success"
+ }
+ ```
### 11. `/index/api/kick_sessions`
- - Function: Disconnects TCP connections, such as RTSP or RTMP players.
-
- - Example:[http://127.0.0.1/index/api/kick_sessions?local_port=554](http://127.0.0.1/index/api/kick_sessions?local_port=554)
+- Function: Disconnects TCP connections, such as RTSP or RTMP players.
- - Parameters:
+- Example:[http://127.0.0.1/index/api/kick_sessions?local_port=554](http://127.0.0.1/index/api/kick_sessions?local_port=554)
- | Parameter | Required | Description |
- | :-----------: | :------: | :-------------------------------------------------------: |
- | secret | Y | API operation key (configured in the configuration file) |
- | local_port | N | Filters local ports, for example, filtering RTSP connections: 554 |
- | peer_ip | N | Filters client IP |
-
- - Response:
+- Parameters:
- ```json
- {
- "code" : 0,
- "count_hit" : 1,# Number of matched clients
- "msg" : "success"
- }
- ```
+| Parameter | Required | Description |
+| :--------: | :------: | :---------------------------------------------------------------: |
+| secret | Y | API operation key (configured in the configuration file) |
+| local_port | N | Filters local ports, for example, filtering RTSP connections: 554 |
+| peer_ip | N | Filters client IP |
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "count_hit" : 1,# Number of matched clients
+ "msg" : "success"
+ }
+ ```
### 12. `/index/api/addStreamProxy`
- Function: Dynamically add RTSP/RTMP/HLS/HTTP-TS/HTTP-FLV pull streaming proxies (only supports H264/H265/AAC/G711/Opus payloads).
-
- - Example:[http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2](http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2)
-
- - Parameters:
-
- | Parameter | Type | Description | Required |
- | :---------------: | :------: | :----------------------------------------------------------: | :------: |
- | secret | `string` | API operation key (configured) | Y |
- | vhost | `string` | Virtual host of the added stream (e.g., `__defaultVhost__`) | Y |
- | app | `string` | Application name of the added stream (e.g., live) | Y |
- | stream | `string` | ID of the added stream (e.g., test) | Y |
- | url | `string` | Stream URL for pulling (e.g., rtmp://live.hkstv.hk.lxdns.com/live/hks2) | Y |
- | retry_count | `int` | Number of pull retry attempts, default is -1 for unlimited retries | N |
- | rtp_type | `int` | RTP pulling type for RTSP streams: 0: TCP, 1: UDP, 2: Multicast | N |
- | timeout_sec | `int` | Pulling timeout in seconds, float type | N |
- | `enable_hls` | `bool` | Whether to convert to HLS-MPEGTS protocol | N |
- | `enable_hls_fmp4` | `bool` | Whether to convert to HLS-FMP4 protocol | N |
- | `enable_mp4` | `bool` | Whether to enable MP4 recording | N |
- | `enable_rtsp` | `bool` | Whether to convert to RTSP protocol | N |
- | `enable_rtmp` | `bool` | Whether to convert to RTMP/FLV protocol | N |
- | `enable_ts` | `bool` | Whether to convert to HTTP-TS/WS-TS protocol | N |
- | `enable_fmp4` | `bool` | Whether to convert to HTTP-FMP4/WS-FMP4 protocol | N |
- | `hls_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
- | `rtsp_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
- | `rtmp_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
- | `ts_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
- | `fmp4_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
- | `enable_audio` | `bool` | Whether to enable audio when converting | N |
- | `add_mute_audio` | `bool` | Whether to add silent AAC audio when there is no audio | N |
- | `mp4_save_path` | `string` | Root directory for saving MP4 recording files, use default if empty | N |
- | `mp4_max_second` | `int` | Maximum duration of MP4 recording slices in seconds | N |
- | `mp4_as_player` | `bool` | Whether MP4 recording counts as a viewer for counting the number of viewers | N |
- | `hls_save_path` | `string` | The root directory where the hls file is saved, leave it blank and use the default | N |
- | `modify_stamp` | `int` | Whether this stream enables timestamp coverage (0: absolute timestamp/1: system timestamp/2: relative timestamp) | N |
- | `auto_close` | `bool` | Whether to automatically close the stream if no one is watching it (without triggering the unwatched hook) | N |
-
- - Response:
-
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "__defaultVhost__/proxy/0" # The unique identifier of the stream
- }
- }
- ```
+Function: Dynamically add RTSP/RTMP/HLS/HTTP-TS/HTTP-FLV pull streaming proxies (only supports H264/H265/AAC/G711/Opus payloads).
+- Example:[http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2](http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2)
+- Parameters:
-### 13. `/index/api/delStreamProxy (Can also be replaced with the close_streams interface after successful stream registration)`
+ | Parameter | Type | Description | Required |
+ | :---------------: | :------: | :--------------------------------------------------------------------------------------------------------------: | :------: |
+ | secret | `string` | API operation key (configured) | Y |
+ | vhost | `string` | Virtual host of the added stream (e.g., `__defaultVhost__`) | Y |
+ | app | `string` | Application name of the added stream (e.g., live) | Y |
+ | stream | `string` | ID of the added stream (e.g., test) | Y |
+ | url | `string` | Stream URL for pulling (e.g., rtmp://live.hkstv.hk.lxdns.com/live/hks2) | Y |
+ | retry_count | `int` | Number of pull retry attempts, default is -1 for unlimited retries | N |
+ | rtp_type | `int` | RTP pulling type for RTSP streams: 0: TCP, 1: UDP, 2: Multicast | N |
+ | timeout_sec | `int` | Pulling timeout in seconds, float type | N |
+ | `enable_hls` | `bool` | Whether to convert to HLS-MPEGTS protocol | N |
+ | `enable_hls_fmp4` | `bool` | Whether to convert to HLS-FMP4 protocol | N |
+ | `enable_mp4` | `bool` | Whether to enable MP4 recording | N |
+ | `enable_rtsp` | `bool` | Whether to convert to RTSP protocol | N |
+ | `enable_rtmp` | `bool` | Whether to convert to RTMP/FLV protocol | N |
+ | `enable_ts` | `bool` | Whether to convert to HTTP-TS/WS-TS protocol | N |
+ | `enable_fmp4` | `bool` | Whether to convert to HTTP-FMP4/WS-FMP4 protocol | N |
+ | `hls_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
+ | `rtsp_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
+ | `rtmp_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
+ | `ts_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
+ | `fmp4_demand` | `bool` | Whether the protocol generates only if someone is watching | N |
+ | `enable_audio` | `bool` | Whether to enable audio when converting | N |
+ | `add_mute_audio` | `bool` | Whether to add silent AAC audio when there is no audio | N |
+ | `mp4_save_path` | `string` | Root directory for saving MP4 recording files, use default if empty | N |
+ | `mp4_max_second` | `int` | Maximum duration of MP4 recording slices in seconds | N |
+ | `mp4_as_player` | `bool` | Whether MP4 recording counts as a viewer for counting the number of viewers | N |
+ | `hls_save_path` | `string` | The root directory where the hls file is saved, leave it blank and use the default | N |
+ | `modify_stamp` | `int` | Whether this stream enables timestamp coverage (0: absolute timestamp/1: system timestamp/2: relative timestamp) | N |
+ | `auto_close` | `bool` | Whether to automatically close the stream if no one is watching it (without triggering the unwatched hook) | N |
- - Function: Close pull streaming proxy.
+- Response:
- - Example:[http://127.0.0.1/index/api/delStreamProxy?key=`__defaultVhost__`/proxy/0](http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0)
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "__defaultVhost__/proxy/0" # The unique identifier of the stream
+ }
+ }
+ ```
- - Parameters:
+### 13. `/index/api/delStreamProxy (Can also be replaced with the close_streams interface after successful stream registration)`
- | Parameter | Required | Description |
- | :-------: | :------: | :----------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the configuration file) |
- | key | Y | The key returned by the addStreamProxy interface |
+- Function: Close pull streaming proxy.
- - Response:
+- Example:[http://127.0.0.1/index/api/delStreamProxy?key=`__defaultVhost__`/proxy/0](http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0)
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # Success or failure
- }
- }
- ```
+- Parameters:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :-------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the configuration file) |
+ | key | Y | The key returned by the addStreamProxy interface |
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # Success or failure
+ }
+ }
+ ```
### 14. `/index/api/addFFmpegSource`
- - Function: Pull stream proxy by forking FFmpeg process, supports any protocol.
-
- - Example:[http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd](http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd)
-
- - Parameters:
-
- | Parameter | Required | Description |
- | :-------------: | :------: | :----------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the configuration file) |
- | src_url | Y | FFmpeg pulling stream address, supports any protocol or format (as long as FFmpeg supports it) |
- | dst_url | Y | FFmpeg rtmp push stream address, usually push to oneself, for example, rtmp://127.0.0.1/live/stream_from_ffmpeg |
- | timeout_ms | Y | Timeout for successful FFmpeg stream pushing |
- | enable_hls | Y | Whether to enable HLS recording |
- | enable_mp4 | Y | Whether to enable MP4 recording |
- | ffmpeg_cmd_key | N | Key for FFmpeg command parameter template in the configuration file (not content), if left empty, the default template `ffmpeg.cmd` will be used |
-
- - Response:
-
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "5f748d2ef9712e4b2f6f970c1d44d93a" # Unique key
- }
- }
- ```
-
+- Function: Pull stream proxy by forking FFmpeg process, supports any protocol.
+- Example:[http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd](http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd)
-### 15. `/index/api/delFFmpegSource (Can also be replaced with the close_streams interface after successful stream registration)`
+- Parameters:
- - Function: Close FFmpeg stream proxy.
+ | Parameter | Required | Description |
+ | :------------: | :------: | :----------------------------------------------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the configuration file) |
+ | src_url | Y | FFmpeg pulling stream address, supports any protocol or format (as long as FFmpeg supports it) |
+ | dst_url | Y | FFmpeg rtmp push stream address, usually push to oneself, for example, rtmp://127.0.0.1/live/stream_from_ffmpeg |
+ | timeout_ms | Y | Timeout for successful FFmpeg stream pushing |
+ | enable_hls | Y | Whether to enable HLS recording |
+ | enable_mp4 | Y | Whether to enable MP4 recording |
+ | ffmpeg_cmd_key | N | Key for FFmpeg command parameter template in the configuration file (not content), if left empty, the default template `ffmpeg.cmd` will be used |
+
+- Response:
- - Example: [http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a](http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a)
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "5f748d2ef9712e4b2f6f970c1d44d93a" # Unique key
+ }
+ }
+ ```
- - Parameters:
+### 15. `/index/api/delFFmpegSource (Can also be replaced with the close_streams interface after successful stream registration)`
- | Parameter | Required | Description |
- | :-------: | :------: | :----------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the configuration file) |
- | key | Y | The key returned by the addFFmpegSource interface |
+- Function: Close FFmpeg stream proxy.
+- Example: [http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a](http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a)
- - Response:
+- Parameters:
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # Success or failure
- }
- }
- ```
+ | Parameter | Required | Description |
+ | :-------: | :------: | :-------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the configuration file) |
+ | key | Y | The key returned by the addFFmpegSource interface |
-
+- Response:
+
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # Success or failure
+ }
+ }
+ ```
### 16. `/index/api/isMediaOnline (Deprecated, please use getMediaList API instead)`
@@ -731,14 +696,13 @@ typedef enum {
- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :------------------------------------------------: |
- | secret | Y | API operation secret key (configured) |
- | schema | Y | Protocol, e.g., rtsp or rtmp |
- | vhost | Y | Virtual host, e.g., __defaultVhost__ |
- | app | Y | Application name, e.g., live |
- | stream | Y | Stream ID, e.g., obs |
-
+ | Parameter | Required | Description |
+ | :-------: | :------: | :-----------------------------------: |
+ | secret | Y | API operation secret key (configured) |
+ | schema | Y | Protocol, e.g., rtsp or rtmp |
+ | vhost | Y | Virtual host, e.g., **defaultVhost** |
+ | app | Y | Application name, e.g., live |
+ | stream | Y | Stream ID, e.g., obs |
- Response:
@@ -749,8 +713,6 @@ typedef enum {
}
```
-
-
### 17. `/index/api/getMediaInfo (Deprecated, please use getMediaList API instead)`
- Function: Get information about the stream.
@@ -759,14 +721,13 @@ typedef enum {
- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :------------------------------------------------: |
- | secret | Y | API operation secret key (configured) |
- | schema | Y | Protocol, e.g., rtsp or rtmp |
- | vhost | Y | Virtual host, e.g., __defaultVhost__ |
- | app | Y | Application name, e.g., live |
- | stream | Y | Stream ID, e.g., obs |
-
+ | Parameter | Required | Description |
+ | :-------: | :------: | :-----------------------------------: |
+ | secret | Y | API operation secret key (configured) |
+ | schema | Y | Protocol, e.g., rtsp or rtmp |
+ | vhost | Y | Virtual host, e.g., **defaultVhost** |
+ | app | Y | Application name, e.g., live |
+ | stream | Y | Stream ID, e.g., obs |
- Response:
@@ -780,7 +741,7 @@ typedef enum {
{
"channels" : 1, # Number of audio channels
"codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # Codec type name
+ "codec_id_name" : "CodecAAC", # Codec type name
"codec_type" : 1, # Video = 0, Audio = 1
"ready" : true, # Whether the track is ready
"sample_bit" : 16, # Audio sample bit depth
@@ -788,7 +749,7 @@ typedef enum {
},
{
"codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # Codec type name
+ "codec_id_name" : "CodecH264", # Codec type name
"codec_type" : 0, # Video = 0, Audio = 1
"fps" : 59, # Video fps
"height" : 720, # Video height
@@ -801,505 +762,472 @@ typedef enum {
### 18. `/index/api/getRtpInfo`
- - Function: Get the RTP information of a specific SSRC when proxying RTP.
-
- - Example:[http://127.0.0.1/index/api/getRtpInfo?stream_id=1A2B3C4D](http://127.0.0.1/index/api/getRtpInfo?ssrc=1A2B3C4D)
+- Function: Get the RTP information of a specific SSRC when proxying RTP.
- - Parameters:
-
- | Parameter | Required | Description |
- | :--------: | :------: | :--------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | stream_id | Y | The SSRC of RTP, in hexadecimal string or the ID of the stream (specified in the openRtpServer interface) |
+- Example:[http://127.0.0.1/index/api/getRtpInfo?stream_id=1A2B3C4D](http://127.0.0.1/index/api/getRtpInfo?ssrc=1A2B3C4D)
+- Parameters:
- - Response:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :-------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | stream_id | Y | The SSRC of RTP, in hexadecimal string or the ID of the stream (specified in the openRtpServer interface) |
- ```json
- {
- "code" : 0,
- "exist" : true, # Whether it exists
- "peer_ip" : "192.168.0.23", # Client IP address for streaming
- "peer_port" : 54000 # Client port
- "local_ip" : "0.0.0.0", # Local listening network card IP
- "local_port" : 10000
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code" : 0,
+ "exist" : true, # Whether it exists
+ "peer_ip" : "192.168.0.23", # Client IP address for streaming
+ "peer_port" : 54000 # Client port
+ "local_ip" : "0.0.0.0", # Local listening network card IP
+ "local_port" : 10000
+ }
+ ```
### 19. `/index/api/getMp4RecordFile`
- - Function: Search the file system to get the list of recorded files or date folders corresponding to a stream.
+- Function: Search the file system to get the list of recorded files or date folders corresponding to a stream.
- - Example:[http://127.0.0.1/index/api/getMp4RecordFile?vhost=`__defaultVhost__`&app=live&stream=ss&period=2020-01](http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01)
+- Example:[http://127.0.0.1/index/api/getMp4RecordFile?vhost=`__defaultVhost__`&app=live&stream=ss&period=2020-01](http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01)
- - Parameters:
+- Parameters:
- | Parameter | Required | Description |
- | :-------: | :------: | :--------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | vhost | Y | Virtual host name of the stream |
- | app | Y | Application name of the stream |
- | stream | Y | ID of the stream |
- | period | Y | Recording date of the stream in the format "2020-02-01". If it's not a complete date, it searches for the list of recording folders. Otherwise, it searches for the list of MP4 files for the specified date. |
- | customized_path | N | Customized search path, same as the `customized_path` in the `startRecord` method. Defaults to the path in the configuration file. |
+ | Parameter | Required | Description |
+ | :-------------: | :------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | vhost | Y | Virtual host name of the stream |
+ | app | Y | Application name of the stream |
+ | stream | Y | ID of the stream |
+ | period | Y | Recording date of the stream in the format "2020-02-01". If it's not a complete date, it searches for the list of recording folders. Otherwise, it searches for the list of MP4 files for the specified date. |
+ | customized_path | N | Customized search path, same as the `customized_path` in the `startRecord` method. Defaults to the path in the configuration file. |
+- Response:
- - Response:
+ ```json
+ # Search folder list (matching by prefix rule): period = 2020-01
+ {
+ "code" : 0,
+ "data" : {
+ "paths" : [ "2020-01-25", "2020-01-24" ],
+ "rootPath" : "/www/record/live/ss/"
+ }
+ }
- ```json
- # Search folder list (matching by prefix rule): period = 2020-01
- {
- "code" : 0,
- "data" : {
- "paths" : [ "2020-01-25", "2020-01-24" ],
- "rootPath" : "/www/record/live/ss/"
- }
- }
-
- # Search MP4 file list: period = 2020-01-24
- {
- "code" : 0,
- "data" : {
- "paths" : [
- "22-20-30.mp4",
- "22-13-12.mp4",
- "21-57-07.mp4",
- "21-19-18.mp4",
- "21-24-21.mp4",
- "21-15-10.mp4",
- "22-14-14.mp4"
- ],
- "rootPath" : "/www/live/ss/2020-01-24/"
- }
- }
-
- ```
+ # Search MP4 file list: period = 2020-01-24
+ {
+ "code" : 0,
+ "data" : {
+ "paths" : [
+ "22-20-30.mp4",
+ "22-13-12.mp4",
+ "21-57-07.mp4",
+ "21-19-18.mp4",
+ "21-24-21.mp4",
+ "21-15-10.mp4",
+ "22-14-14.mp4"
+ ],
+ "rootPath" : "/www/live/ss/2020-01-24/"
+ }
+ }
-
+ ```
### 20. `/index/api/startRecord`
- - Function: Start recording in HLS or MP4 format.
+- Function: Start recording in HLS or MP4 format.
- - Example:[http://127.0.0.1/index/api/startRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/startRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
-
- - Parameters:
-
- | Parameter | Required | Description | Type |
- | :------------: | :------: | :--------------------------------------------------: | :----: |
- | secret | Y | API access key (configured in file) | string |
- | type | Y | 0 for HLS, 1 for MP4 format | 0/1 |
- | vhost | Y | Virtual host, e.g., "__defaultVhost__" | string |
- | app | Y | Application name, e.g., "live" | string |
- | stream | Y | Stream ID, e.g., "obs" | string |
- | customized_path | N | Directory for storing the recordings | string |
- | max_second | N | Maximum duration of MP4 recording segments in seconds. Set to 0 to use the configured value. | int |
+- Example:[http://127.0.0.1/index/api/startRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/startRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- Parameters:
- - Response:
+| Parameter | Required | Description | Type |
+| :-------------: | :------: | :------------------------------------------------------------------------------------------: | :----: |
+| secret | Y | API access key (configured in file) | string |
+| type | Y | 0 for HLS, 1 for MP4 format | 0/1 |
+| vhost | Y | Virtual host, e.g., "**defaultVhost**" | string |
+| app | Y | Application name, e.g., "live" | string |
+| stream | Y | Stream ID, e.g., "obs" | string |
+| customized_path | N | Directory for storing the recordings | string |
+| max_second | N | Maximum duration of MP4 recording segments in seconds. Set to 0 to use the configured value. | int |
- ```json
- {
- "code" : 0,
- "result" : true # success or failure
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code" : 0,
+ "result" : true # success or failure
+ }
+ ```
### 21. `/index/api/stopRecord`
- - Function: Stop recording the stream.
-
- - Example:[http://127.0.0.1/index/api/stopRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/stopRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
-
- - Parameters:
+- Function: Stop recording the stream.
- | Parameter | Required | Description |
- | :---------: | :------: | :----------------------------------------------: |
- | secret | Y | API access key (configured in file) |
- | type | Y | 0 for HLS, 1 for MP4 format |
- | vhost | Y | Virtual host, e.g., "__defaultVhost__" |
- | app | Y | Application name, e.g., "live" |
- | stream | Y | Stream ID, e.g., "obs" |
+- Example:[http://127.0.0.1/index/api/stopRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/stopRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- Parameters:
- - Response:
+| Parameter | Required | Description |
+| :-------: | :------: | :------------------------------------: |
+| secret | Y | API access key (configured in file) |
+| type | Y | 0 for HLS, 1 for MP4 format |
+| vhost | Y | Virtual host, e.g., "**defaultVhost**" |
+| app | Y | Application name, e.g., "live" |
+| stream | Y | Stream ID, e.g., "obs" |
- ```json
- {
- "code" : 0,
- "result" : true # success or failure
- }
- ```
+- Response:
-
+ ```json
+ {
+ "code" : 0,
+ "result" : true # success or failure
+ }
+ ```
### 22. `/index/api/isRecording`
- - Function: Get the recording status of the stream.
+- Function: Get the recording status of the stream.
- - Example:[http://127.0.0.1/index/api/isRecording?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isRecording?type=1&vhost=__defaultVhost__&app=live&stream=obs)
-
- - Parameters:
-
- | Parameter | Required | Description |
- | :---------: | :------: | :----------------------------------------------: |
- | secret | Y | API access key (configured in file) |
- | type | Y | 0 for HLS, 1 for MP4 format |
- | vhost | Y | Virtual host, e.g., "__defaultVhost__" |
- | app | Y | Application name, e.g., "live" |
- | stream | Y | Stream ID, e.g., "obs" |
+- Example:[http://127.0.0.1/index/api/isRecording?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isRecording?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- Parameters:
- - Response:
+| Parameter | Required | Description |
+| :-------: | :------: | :------------------------------------: |
+| secret | Y | API access key (configured in file) |
+| type | Y | 0 for HLS, 1 for MP4 format |
+| vhost | Y | Virtual host, e.g., "**defaultVhost**" |
+| app | Y | Application name, e.g., "live" |
+| stream | Y | Stream ID, e.g., "obs" |
- ```json
- {
- "code" : 0,
- "status" : true # false: not recording, true: currently recording
- }
- ```
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "status" : true # false: not recording, true: currently recording
+ }
+ ```
### 23. `/index/api/getSnap`
- - Function: Get a screenshot or generate a real-time screenshot and return it.
-
- - Example:[http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30](http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30)
-
- - Parameters:
+- Function: Get a screenshot or generate a real-time screenshot and return it.
- | Parameter | Required | Description |
- | :---------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation secret key (configured file) |
- | url | Y | The URL of the image to capture, which can be local or remote. |
- | timeout_sec | Y | Timeout for capturing the image to prevent FFmpeg from waiting indefinitely. |
- | expire_sec | Y | Expiration time for the captured image cache. All images generated within this time will be returned as cache. |
+- Example:[http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30](http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30)
+- Parameters:
- - Response:
-
- ```json
- The image in JPEG format, can be directly opened in a browser.
- ```
+ | Parameter | Required | Description |
+ | :---------: | :------: | :------------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured file) |
+ | url | Y | The URL of the image to capture, which can be local or remote. |
+ | timeout_sec | Y | Timeout for capturing the image to prevent FFmpeg from waiting indefinitely. |
+ | expire_sec | Y | Expiration time for the captured image cache. All images generated within this time will be returned as cache. |
+- Response:
+ ```json
+ The image in JPEG format, can be directly opened in a browser.
+ ```
### 24. `/index/api/openRtpServer`
- - Function: Create a GB28181 RTP receiving port. If the port times out receiving data, it will be automatically released (no need to call the closeRtpServer interface).
+- Function: Create a GB28181 RTP receiving port. If the port times out receiving data, it will be automatically released (no need to call the closeRtpServer interface).
- - Example:[http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test](http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test)
+- Example:[http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test](http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test)
- - Parameters:
-
- | Parameter | Required | Description |
- | :--------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation secret key (configured file) |
- | port | Y | Receiving port. If set to 0, a random port will be used. |
- | tcp_mode | Y | 0 for UDP mode, 1 for TCP passive mode, 2 for TCP active mode (compatible with enable_tcp: 0/1). |
- | stream_id | Y | The stream ID bound to this port. Only this stream can be created on this port (not multiple streams based on SSRC). |
-
-
- - Response:
+- Parameters:
- ```json
- {
- "code" : 0,
- "port" : 55463 # Receiving port for easy reference to the random port number.
- ```
+ | Parameter | Required | Description |
+ | :-------: | :------: | :------------------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured file) |
+ | port | Y | Receiving port. If set to 0, a random port will be used. |
+ | tcp_mode | Y | 0 for UDP mode, 1 for TCP passive mode, 2 for TCP active mode (compatible with enable_tcp: 0/1). |
+ | stream_id | Y | The stream ID bound to this port. Only this stream can be created on this port (not multiple streams based on SSRC). |
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "port" : 55463 # Receiving port for easy reference to the random port number.
+ ```
### 25. `/index/api/closeRtpServer`
- - Function: Close the GB28181 RTP receiving port.
-
- - Example:[http://127.0.0.1/index/api/closeRtpServer?stream_id=test](http://127.0.0.1/index/api/closeRtpServer?stream_id=test)
+- Function: Close the GB28181 RTP receiving port.
- - Parameters:
+- Example:[http://127.0.0.1/index/api/closeRtpServer?stream_id=test](http://127.0.0.1/index/api/closeRtpServer?stream_id=test)
- | Parameter | Required | Description |
- | :-------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation secret key (configured file) |
- | stream_id | Y | Stream ID provided when calling the openRtpServer interface. |
+- Parameters:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :----------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured file) |
+ | stream_id | Y | Stream ID provided when calling the openRtpServer interface. |
- - Response:
+- Response:
- ```json
- {
- "code": 0,
- "hit": 1 # Whether the record was found and closed.
- }
- ```
+ ```json
+ {
+ "code": 0,
+ "hit": 1 # Whether the record was found and closed.
+ }
+ ```
### 26. `/index/api/listRtpServer`
- - Function: Get all RTP servers created by the openRtpServer interface.
-
- - Example:[http://127.0.0.1/index/api/listRtpServer](http://127.0.0.1/index/api/listRtpServer)
+- Function: Get all RTP servers created by the openRtpServer interface.
- - Parameters:
-
- | Parameter | Required | Description |
- | :-------: | :------: | :------------------------------------------: |
- | secret | Y | API operation key (configured in file) |
+- Example:[http://127.0.0.1/index/api/listRtpServer](http://127.0.0.1/index/api/listRtpServer)
+- Parameters:
- - Response:
+ | Parameter | Required | Description |
+ | :-------: | :------: | :------------------------------------: |
+ | secret | Y | API operation key (configured in file) |
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "port" : 52183, # Bound port number
- "stream_id" : "test" # Bound stream ID
- }
- ]
- }
- ```
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "port" : 52183, # Bound port number
+ "stream_id" : "test" # Bound stream ID
+ }
+ ]
+ }
+ ```
### 27. `/index/api/startSendRtp`
- - Function: Start ps-rtp streaming as a GB28181 client, supporting rtp/udp mode. This interface supports converting protocols such as rtsp/rtmp to ps-rtp streaming. The first streaming attempt failure will return an error directly. After a successful attempt, subsequent failures will be retried indefinitely.
- - Example:[http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0](http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0)
-
- - Parameters:
+- Function: Start ps-rtp streaming as a GB28181 client, supporting rtp/udp mode. This interface supports converting protocols such as rtsp/rtmp to ps-rtp streaming. The first streaming attempt failure will return an error directly. After a successful attempt, subsequent failures will be retried indefinitely.
+- Example:[http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0](http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0)
- | Parameter | Required | Description |
- | :---------: | :------: | :---------------------------------------------------------: |
- | secret | Y | API operation key (configured in file) |
- | vhost | Y | Virtual host, for example __defaultVhost__ |
- | app | Y | Application name, for example live |
- | stream | Y | Stream ID, for example test |
- | ssrc | Y | SSRC of the RTP stream. Specifying different SSRCs can stream to multiple servers simultaneously |
- | dst_url | Y | Destination IP or domain |
- | dst_port | Y | Destination port number |
- | is_udp | Y | Whether it is UDP mode, otherwise it is TCP mode |
- | src_port | N | Local port used, default to a random port if set to 0 or not provided |
- | pt | N | RTP payload type (uint8_t) when sending, default to 96 if not provided |
- | use_ps | N | RTP payload type when sending. Set to 1 for PS payload, 0 for ES payload. Default to 1 if not provided |
- | only_audio | N | Effective when use_ps is 0. Set to 1 to send audio, 0 to send video. Default to 0 if not provided |
-
+- Parameters:
+ | Parameter | Required | Description |
+ | :--------: | :------: | :----------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation key (configured in file) |
+ | vhost | Y | Virtual host, for example **defaultVhost** |
+ | app | Y | Application name, for example live |
+ | stream | Y | Stream ID, for example test |
+ | ssrc | Y | SSRC of the RTP stream. Specifying different SSRCs can stream to multiple servers simultaneously |
+ | dst_url | Y | Destination IP or domain |
+ | dst_port | Y | Destination port number |
+ | is_udp | Y | Whether it is UDP mode, otherwise it is TCP mode |
+ | src_port | N | Local port used, default to a random port if set to 0 or not provided |
+ | pt | N | RTP payload type (uint8_t) when sending, default to 96 if not provided |
+ | use_ps | N | RTP payload type when sending. Set to 1 for PS payload, 0 for ES payload. Default to 1 if not provided |
+ | only_audio | N | Effective when use_ps is 0. Set to 1 to send audio, 0 to send video. Default to 0 if not provided |
- - Response:
+- Response:
- ```json
- {
- "code": 0, # Success
- "local_port": 57152 # Local port number used
- }
- ```
+ ```json
+ {
+ "code": 0, # Success
+ "local_port": 57152 # Local port number used
+ }
+ ```
#### 27.1. `/index/api/startSendRtpPassive`
- - Function: Acts as a GB28181 Passive TCP server. This interface supports the conversion of protocols such as RTSP/RTMP to PS-RTP for passive streaming. When calling this interface, zlm will start a TCP server and wait for connection requests. After the connection is established, zlm will close the TCP server and continuously stream to the client. If the first streaming attempt fails, an error will be returned directly. Once successful, subsequent failures will be retried indefinitely (continuously establishing TCP listening and closing after timeout).
- - Example: [http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1](http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1)
-
- - Parameters:
-
- | Parameters | Required | Description |
- | :--------: | :------: | :---------------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | vhost | Y | Virtual host, for example, __defaultVhost__ |
- | app | Y | Application name, for example, live |
- | stream | Y | Stream ID, for example, test |
- | ssrc | Y | SSRC of the RTP stream, specifying different SSRCs allows streaming to multiple servers simultaneously |
- | src_port | N | Local port used; defaults to a random port if 0 or not specified |
- | pt | N | PT (uint8_t) for RTP when sending; defaults to 96 if not specified |
- | use_ps | N | Payload type for RTP when sending. If 1, payload is PS; if 0, payload is ES; defaults to 1 if not specified |
- | only_audio | N | Valid when use_ps is 0. If 1, audio is sent; if 0, video is sent; defaults to 0 if not specified |
-
-
+- Function: Acts as a GB28181 Passive TCP server. This interface supports the conversion of protocols such as RTSP/RTMP to PS-RTP for passive streaming. When calling this interface, zlm will start a TCP server and wait for connection requests. After the connection is established, zlm will close the TCP server and continuously stream to the client. If the first streaming attempt fails, an error will be returned directly. Once successful, subsequent failures will be retried indefinitely (continuously establishing TCP listening and closing after timeout).
+- Example: [http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=**defaultVhost**&app=live&stream=test&ssrc=1](http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1)
+- Parameters:
- - Response:
+ | Parameters | Required | Description |
+ | :--------: | :------: | :---------------------------------------------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | vhost | Y | Virtual host, for example, **defaultVhost** |
+ | app | Y | Application name, for example, live |
+ | stream | Y | Stream ID, for example, test |
+ | ssrc | Y | SSRC of the RTP stream, specifying different SSRCs allows streaming to multiple servers simultaneously |
+ | src_port | N | Local port used; defaults to a random port if 0 or not specified |
+ | pt | N | PT (uint8_t) for RTP when sending; defaults to 96 if not specified |
+ | use_ps | N | Payload type for RTP when sending. If 1, payload is PS; if 0, payload is ES; defaults to 1 if not specified |
+ | only_audio | N | Valid when use_ps is 0. If 1, audio is sent; if 0, video is sent; defaults to 0 if not specified |
- ```json
- {
- "code": 0, # Success
- "local_port": 57152 # Local port number used
- }
- ```
+- Response:
+ ```json
+ {
+ "code": 0, # Success
+ "local_port": 57152 # Local port number used
+ }
+ ```
### 28. `/index/api/stopSendRtp`
- - Function: Stops GB28181 PS-RTP push streaming.
- - Example: [http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test](http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test)
-
- - Parameters:
+- Function: Stops GB28181 PS-RTP push streaming.
+- Example: [http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=**defaultVhost**&app=live&stream=test](http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test)
- | Parameters | Required | Description |
- | :--------: | :------: | :---------------------------------------------------------------: |
- | secret | Y | API operation secret key (configured in the file) |
- | vhost | Y | Virtual host, for example, __defaultVhost__ |
- | app | Y | Application name, for example, live |
- | stream | Y | Stream ID, for example, test |
- | ssrc | N | Stop RTP streaming for a specific SSRC, or close all streams if empty |
-
+- Parameters:
+ | Parameters | Required | Description |
+ | :--------: | :------: | :-------------------------------------------------------------------: |
+ | secret | Y | API operation secret key (configured in the file) |
+ | vhost | Y | Virtual host, for example, **defaultVhost** |
+ | app | Y | Application name, for example, live |
+ | stream | Y | Stream ID, for example, test |
+ | ssrc | N | Stop RTP streaming for a specific SSRC, or close all streams if empty |
- - Response:
+- Response:
- ```json
- {
- "code": 0 # Success
- }
- ```
+ ```json
+ {
+ "code": 0 # Success
+ }
+ ```
### 29. `/index/api/getStatistic`
- - Function: Get statistics on the number of main objects, mainly used for analyzing memory performance.
- - Example:[http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc](http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc)
-
- - Parameters:
+- Function: Get statistics on the number of main objects, mainly used for analyzing memory performance.
+- Example:[http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc](http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc)
- | Parameter | Required | Description |
- | :-------: | :------: | :---------------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
+- Parameters:
+| Parameter | Required | Description |
+| :-------: | :------: | :----------------------------------------: |
+| secret | Y | API operation key (configured in the file) |
- - Response:
+- Response:
- ```json
- {
+ ```json
+ {
"code": 0,
"data": {
- "Buffer": 2,
- "BufferLikeString": 1,
- "BufferList": 0,
- "BufferRaw": 1,
- "Frame": 0,
- "FrameImp": 0,
- "MediaSource": 0,
- "MultiMediaSourceMuxer": 0,
- "Socket": 66,
- "TcpClient": 0,
- "TcpServer": 64,
- "TcpSession": 1
+ "Buffer": 2,
+ "BufferLikeString": 1,
+ "BufferList": 0,
+ "BufferRaw": 1,
+ "Frame": 0,
+ "FrameImp": 0,
+ "MediaSource": 0,
+ "MultiMediaSourceMuxer": 0,
+ "Socket": 66,
+ "TcpClient": 0,
+ "TcpServer": 64,
+ "TcpSession": 1
}
- }
- ```
+ }
+ ```
### 30. `/index/api/addStreamPusherProxy`
- - Function: Add active RTSP/RTMP stream pusher (push the live stream from this server to another server).
+- Function: Add active RTSP/RTMP stream pusher (push the live stream from this server to another server).
- - Example:[http://127.0.0.1/index/api/addStreamPusherProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2](http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2)
+- Example:[http://127.0.0.1/index/api/addStreamPusherProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2](http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2)
- - Parameters:
-
- | Parameter | Required | Description |
- | :-----------: | :------: | :---------------------------------------------: |
- | secret | Y | API operation key (configured in the file) |
- | vhost | Y | Virtual host of the added stream, for example, `__defaultVhost__` |
- | schema | Y | Protocol, e.g., rtsp or rtmp |
- | app | Y | Application name of the added stream, e.g., live |
- | stream | Y | Stream ID to be pushed |
- | dst_url | Y | Destination push URL, if it contains parameters, they need to be URL-encoded |
- | retry_count | N | Retry count for failed push, unlimited by default |
- | rtp_type | N | Pushing method for RTSP stream, 0: TCP, 1: UDP |
- | timeout_sec | N | Push timeout in seconds, float type |
-
- - Response:
+- Parameters:
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12" # Unique identifier of the stream
- }
- }
- ```
+| Parameter | Required | Description |
+| :---------: | :------: | :--------------------------------------------------------------------------: |
+| secret | Y | API operation key (configured in the file) |
+| vhost | Y | Virtual host of the added stream, for example, `__defaultVhost__` |
+| schema | Y | Protocol, e.g., rtsp or rtmp |
+| app | Y | Application name of the added stream, e.g., live |
+| stream | Y | Stream ID to be pushed |
+| dst_url | Y | Destination push URL, if it contains parameters, they need to be URL-encoded |
+| retry_count | N | Retry count for failed push, unlimited by default |
+| rtp_type | N | Pushing method for RTSP stream, 0: TCP, 1: UDP |
+| timeout_sec | N | Push timeout in seconds, float type |
+- Response:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12" # Unique identifier of the stream
+ }
+ }
+ ```
### 31. `/index/api/delStreamPusherProxy(可以使用close_streams接口关闭源直播流也可以停止推流)`
- - Function: Close the stream pushing.
+- Function: Close the stream pushing.
- - Example:[http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12](http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12)
+- Example:[http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/**defaultVhost**/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12](http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12)
- - Parameters:
+- Parameters:
- | Parameter | Required | Explanation |
- | :-------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation key (configured) |
- | key | Y | Key returned by the 'addStreamPusherProxy' interface |
+ | Parameter | Required | Explanation |
+ | :-------: | :------: | :--------------------------------------------------: |
+ | secret | Y | API operation key (configured) |
+ | key | Y | Key returned by the 'addStreamPusherProxy' interface |
- - Response:
+- Response:
+
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # Success or failure
+ }
+ }
+ ```
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # Success or failure
- }
- }
- ```
### 32. `/index/api/version(获取版本信息)`
- - Function: Get version information, such as branch, commit ID, and build time.
+- Function: Get version information, such as branch, commit ID, and build time.
- - Example:[http://127.0.0.1/index/api/version](http://127.0.0.1/index/api/version)
+- Example:[http://127.0.0.1/index/api/version](http://127.0.0.1/index/api/version)
- - Parameters:
+- Parameters:
- | Parameter | Required | Explanation |
- | :-------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation key (configured) |
+ | Parameter | Required | Explanation |
+ | :-------: | :------: | :----------------------------: |
+ | secret | Y | API operation key (configured) |
- - Response:
+- Response:
- ```json
- {
- "code": 0,
- "data": {
- "branchName": "master",
- "buildTime": "2023-04-19T10:34:34",
- "commitHash": "f143898"
- }
+ ```json
+ {
+ "code": 0,
+ "data": {
+ "branchName": "master",
+ "buildTime": "2023-04-19T10:34:34",
+ "commitHash": "f143898"
}
- ```
+ }
+ ```
### 33. `/index/api/getMediaPlayerList`
- - Function: Get the list of viewers for a specific stream.
+- Function: Get the list of viewers for a specific stream.
+
+- Example:[http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=**defaultVhost**&app=live&stream=test'](http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test')
- - Example:[http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test'](http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test')
+- Parameters:
- - Parameters:
+ | Parameter | Required | Explanation |
+ | :-------: | :------: | :------------------------------------: |
+ | secret | Y | API operation key (configured) |
+ | schema | Y | Protocol, e.g., rtsp or rtmp |
+ | vhost | Y | Virtual host, e.g., '**defaultVhost**' |
+ | app | Y | Application name, e.g., live |
+ | stream | Y | Stream ID, e.g., obs |
- | Parameter | Required | Explanation |
- | :-------: | :------: | :--------------------------------------------: |
- | secret | Y | API operation key (configured) |
- | schema | Y | Protocol, e.g., rtsp or rtmp |
- | vhost | Y | Virtual host, e.g., '__defaultVhost__' |
- | app | Y | Application name, e.g., live |
- | stream | Y | Stream ID, e.g., obs |
-
- - Response:
+- Response:
- ```json
- {
- "code": 0,
- "data": [
- {
- "identifier": "3-309",
- "local_ip": "::",
- "local_port": 8000,
- "peer_ip": "172.18.190.159",
- "peer_port": 52996,
- "typeid": "mediakit::WebRtcSession"
- }
- ]
- }
- ```
+```json
+{
+ "code": 0,
+ "data": [
+ {
+ "identifier": "3-309",
+ "local_ip": "::",
+ "local_port": 8000,
+ "peer_ip": "172.18.190.159",
+ "peer_port": 52996,
+ "typeid": "mediakit::WebRtcSession"
+ }
+ ]
+}
+```
diff --git a/src/guide/media_server/sequence_diagram.md b/src/guide/media_server/sequence_diagram.md
index 9d3155f..8eef526 100644
--- a/src/guide/media_server/sequence_diagram.md
+++ b/src/guide/media_server/sequence_diagram.md
@@ -6,12 +6,12 @@ title: Sequence diagram
---
title: On-Demand Pulling Stream Process
---
-sequenceDiagram
+sequenceDiagram
participant Player
participant ZLMediaKit
participant Camera
participant Your Business Server
-
+
Player ->> ZLMediaKit: Player requests rtsp/rtmp/http-flv/ws-flv playback
ZLMediaKit ->> ZLMediaKit: Check if the stream exists
ZLMediaKit ->> Your Business Server: Stream does not exist, trigger web hook (stream_not_found) event
@@ -37,7 +37,7 @@ sequenceDiagram
participant ZLMediaKit
participant Streaming Camera
participant Your Business Server
-
+
Player ->> ZLMediaKit: Player requests rtsp/rtmp/http-flv/ws-flv playback
ZLMediaKit ->> ZLMediaKit: Check if the stream exists
ZLMediaKit ->> Your Business Server: Stream does not exist, trigger web hook (stream_not_found) event
@@ -61,7 +61,7 @@ sequenceDiagram
participant Player
participant ZLMediaKit
participant Your Business Server
-
+
Player ->> ZLMediaKit: Player requests rtsp/rtmp/http-flv/ws-flv/hls playback
ZLMediaKit ->> Your Business Server: Check if the player has permission, trigger web hook (on_play)
Your Business Server -->> ZLMediaKit: Parameters are valid, player has permission to play
@@ -76,7 +76,7 @@ sequenceDiagram
participant Publisher
participant ZLMediaKit
participant Your Business Server
-
+
Publisher ->> ZLMediaKit: rtsp/rtmp stream publishing request
ZLMediaKit ->> Your Business Server: Check if the publisher has permission, trigger web hook (on_publish)
Your Business Server -->> ZLMediaKit: Parameters are valid, publisher has permission to publish
diff --git a/src/guide/media_server/start_server.md b/src/guide/media_server/start_server.md
index e1f0bac..970a53f 100644
--- a/src/guide/media_server/start_server.md
+++ b/src/guide/media_server/start_server.md
@@ -4,6 +4,7 @@ icon: circle-info
---
## Program Path
+
After compiling ZLMediaKit, the MediaServer main program is generated. The relative path of the program is `release/${platform}/${build_type}/MediaServer`.
`${platform}` depends on your operating system, which may be `windows/linux/mac`, and `${build_type}` depends on the compile type you specified when using cmake, which could be `Debug/Release`.
@@ -11,6 +12,7 @@ After compiling ZLMediaKit, the MediaServer main program is generated. The relat
## Start-up and Parameters
- First, please refer to the help for startup parameters:
+
```bash
xzl-mac-pro:Debug xzl$ ./MediaServer -h
-h --help no argument default:null optional print this information
@@ -21,7 +23,9 @@ xzl-mac-pro:Debug xzl$ ./MediaServer -h
-s --ssl argument default:/Users/xzl/git/ZLMediaKit/release/mac/Debug/ssl.p12 optional path of the SSL certificate file or directory, supports p12/pem types
-t --threads argument default:8 optional number of threads to launch for event triggering
```
+
- Explanation:
+
- -d(--daemon): Whether to start as a daemon. The daemon does only one thing: monitor whether the child process (the actual working process) has exited, and attempts to restart the child process if it has exited.
- -l(--level): Specifies the log print level, with values ranging from 0 to 4. The higher the level, the fewer logs are printed.
- -m(--max_day): The number of days the log files are kept. Logs created during the current run of the program will be deleted if they exceed this number of days.
@@ -38,13 +42,15 @@ xzl-mac-pro:Debug xzl$ ./MediaServer -h
- 2. If you are going to use FFmpeg related functions, you should start the program like this: `nohup ./MediaServer -d &`. Otherwise, the fork FFmpeg process may cause the MediaServer process to hang.
## Hot Loading of Configuration Files
+
After modifying and saving the configuration file, enter `killall -1 MediaServer` in the shell to make ZLMediaKit hot load the configuration file. If successful, it will print the following style of logs:
+
![Image](/images/start_server_2.png)
## Stopping the Server
+
- If you started the server in the background, please enter `killall -2 MediaServer` in the shell to gracefully shut down the server (the program will automatically release resources and exit after receiving the SIGINT signal).
- Otherwise, you can press `Ctr + C` to exit the program.
- The logs when MediaServer exits are as follows:
![Image](/images/start_server_3.png)
-
diff --git a/src/guide/media_server/web_hook_api.md b/src/guide/media_server/web_hook_api.md
index 8e7e472..129cf2c 100644
--- a/src/guide/media_server/web_hook_api.md
+++ b/src/guide/media_server/web_hook_api.md
@@ -3,6 +3,7 @@ title: Web Hook
---
## Web Hook Preview
+
MediaServer can notify certain internal events through HTTP POST to a third-party HTTP server. The following are the relevant default configurations:
```ini
@@ -32,7 +33,8 @@ If it is an authentication event and the access IP is `127.0.0.1`, or the authen
You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issues/71).
## Explanation
-### 1. enable :
+
+### 1. enable:
- Explanation:
@@ -48,7 +50,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
- Explanation:
- URL parameters for the super administrator. If the visitor's URL parameters match this, no authentication will be required for RTSP/RTMP/HLS/HTTP-FLV/WS-FLV playback or publishing. This option is for developer debugging.
+ URL parameters for the super administrator. If the visitor's URL parameters match this, no authentication will be required for RTSP/RTMP/HLS/HTTP-FLV/WS-FLV playback or publishing. This option is for developer debugging.
### 4. on_flow_report:
@@ -68,7 +70,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -84,24 +86,23 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"id" : "140259799100960"
}
```
+
- Request Parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :------------: | :------------: | :----------------------------------: |
- | `app` | `string` | Stream application |
- | `duration` | `int` | Duration of TCP connection |
- | `params` | `string` | URL parameters for stream |
- | `player` | `bool` | `true` for player, `false` for publisher |
- | `schema` | `string` | Protocol of playback or publishing (e.g., rtsp, rtmp, http) |
- | `stream` | `string` | Stream ID |
- | `totalBytes` | `int` | Total consumed upstream and downstream traffic in bytes |
- | `vhost` | `string` | Stream virtual host |
- | `ip` | `string` | Client's IP address |
- | `port` | `int` | Client's port number |
- | `id` | `string` | Unique ID of TCP connection |
- | `mediaServerId`| `string` | Server ID set in the configuration file |
-
-
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :------------: | :---------------------------------------------------------: |
+ | `app` | `string` | Stream application |
+ | `duration` | `int` | Duration of TCP connection |
+ | `params` | `string` | URL parameters for stream |
+ | `player` | `bool` | `true` for player, `false` for publisher |
+ | `schema` | `string` | Protocol of playback or publishing (e.g., rtsp, rtmp, http) |
+ | `stream` | `string` | Stream ID |
+ | `totalBytes` | `int` | Total consumed upstream and downstream traffic in bytes |
+ | `vhost` | `string` | Stream virtual host |
+ | `ip` | `string` | Client's IP address |
+ | `port` | `int` | Client's port number |
+ | `id` | `string` | Unique ID of TCP connection |
+ | `mediaServerId` | `string` | Server ID set in the configuration file |
- Default Response:
@@ -113,21 +114,19 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 07:09:32 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
-
- ```
-
+ ```
### 5. on_http_access:
- Explanation:
- Triggered when accessing files on the http file server other than HLS.
+ Triggered when accessing files on the http file server other than HLS.
- Trigger request:
@@ -141,7 +140,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"header.Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
@@ -159,22 +158,22 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"path" : "/live/",
"port" : 65073
}
-
+
```
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Description |
- | :--------------: | :-----------------: | :------------------------------------: |
- | `header.*` | `string` | HTTP client request headers |
- | `id` | `string` | Unique TCP connection ID |
- | `ip` | `string` | HTTP client IP address |
- | `is_dir` | `bool` | Indicates whether the path is a file or directory in the HTTP request |
- | `params` | `string` | HTTP URL parameters |
- | `path` | `string` | Requested file or directory |
- | `port` | `unsigned short` | HTTP client port number |
- | `mediaServerId` | `string` | Server ID set through configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :--------------: | :-------------------------------------------------------------------: |
+ | `header.*` | `string` | HTTP client request headers |
+ | `id` | `string` | Unique TCP connection ID |
+ | `ip` | `string` | HTTP client IP address |
+ | `is_dir` | `bool` | Indicates whether the path is a file or directory in the HTTP request |
+ | `params` | `string` | HTTP URL parameters |
+ | `path` | `string` | Requested file or directory |
+ | `port` | `unsigned short` | HTTP client port number |
+ | `mediaServerId` | `string` | Server ID set through configuration file |
+
- Default response:
```http
@@ -185,35 +184,32 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 07:27:01 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"err" : "",
"path" : "",
"second" : 600
}
-
+
```
- Response parameter details:
- | Parameter Name | Parameter Type | Parameter Description |
- | :--------------: | :-----------------: | :-------------------------------------------------: |
- | `code` | `int` | Always return 0 |
- | `err` | `string` | Error message for disallowed access, leave empty for allowed access |
- | `path` | `string` | The top-level directory that the client can access or is forbidden to access. If it's an empty string, it represents the current directory |
- | `second` | `int` | Validity period of the authorization result for this request, in seconds |
- | `mediaServerId` | `string` | Server ID set through configuration file |
-
-
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
+ | `code` | `int` | Always return 0 |
+ | `err` | `string` | Error message for disallowed access, leave empty for allowed access |
+ | `path` | `string` | The top-level directory that the client can access or is forbidden to access. If it's an empty string, it represents the current directory |
+ | `second` | `int` | Validity period of the authorization result for this request, in seconds |
+ | `mediaServerId` | `string` | Server ID set through configuration file |
### 6. on_play:
- Explanation:
Player authentication event triggered for rtsp/rtmp/http-flv/ws-flv/hls playback. This event is triggered for playback of streams. If the stream does not exist, the on_play event is triggered first, followed by the on_stream_not_found event. When playing an rtsp stream, if the stream has started rtsp-specific authentication (on_rtsp_realm), the on_play event will not be triggered.
-
+
- Trigger request:
```http
@@ -226,7 +222,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -238,23 +234,23 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"stream" : "obs",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Description |
- | :--------------: | :-----------------: | :---------------------------------------------------: |
- | `app` | `string` | Stream application name |
- | `id` | `string` | Unique TCP connection ID |
- | `ip` | `string` | Player IP address |
- | `params` | `string` | Playback URL parameters |
- | `port` | `unsigned short` | Player port number |
- | `schema` | `string` | Playback protocol, which can be rtsp, rtmp, or http |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId` | `string` | Server ID set through configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :--------------: | :-------------------------------------------------: |
+ | `app` | `string` | Stream application name |
+ | `id` | `string` | Unique TCP connection ID |
+ | `ip` | `string` | Player IP address |
+ | `params` | `string` | Playback URL parameters |
+ | `port` | `unsigned short` | Player port number |
+ | `schema` | `string` | Playback protocol, which can be rtsp, rtmp, or http |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID set through configuration file |
+
- Default response:
```http
@@ -265,29 +261,27 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 07:41:21 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
-
- ```
-
-- Response parameter details:
- | Parameter Name | Parameter Type | Parameter Description |
- | :--------------: | :-----------------: | :-------------------------------------------------: |
- | `code` | `int` | Error code, 0 means playback allowed |
- | `msg` | `string` | Error message when playback is not allowed |
-
+ ```
+- Response parameter details:
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :------------: | :------------: | :----------------------------------------: |
+ | `code` | `int` | Error code, 0 means playback allowed |
+ | `msg` | `string` | Error message when playback is not allowed |
### 7. on_publish:
- Explanation:
- RTSP/RTMP/RTP streaming authentication event.
+ RTSP/RTMP/RTP streaming authentication event.
+
- Trigger request:
```http
@@ -300,7 +294,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -312,23 +306,23 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"stream" : "obs",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Description |
- | :------------: | :----------------: | :-----------------------------------------------: |
- | `app` | `string` | Name of the streaming app |
- | `id` | `string` | Unique ID for TCP connection |
- | `ip` | `string` | IP address of the streaming device |
- | `params` | `string` | Parameters for the streaming URL |
- | `port` | `unsigned short` | Port number of the streaming device |
- | `schema` | `string` | Protocol for streaming, possibly RTSP or RTMP |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId` | `string` | Server ID set through configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :--------------: | :-------------------------------------------: |
+ | `app` | `string` | Name of the streaming app |
+ | `id` | `string` | Unique ID for TCP connection |
+ | `ip` | `string` | IP address of the streaming device |
+ | `params` | `string` | Parameters for the streaming URL |
+ | `port` | `unsigned short` | Port number of the streaming device |
+ | `schema` | `string` | Protocol for streaming, possibly RTSP or RTMP |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID set through configuration file |
+
- Default response:
```http
@@ -339,7 +333,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 07:46:43 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"add_mute_audio" : true,
@@ -360,37 +354,38 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"auto_close" : false,
"stream_replace" : ""
}
-
+
```
-
+
- Response parameter details:
- | Parameter Name | Parameter Type | Parameter Description | Required |
- | :---------------: | :------------: | :----------------------------------------------------------: | :------: |
- | `code` | `int` | Error code, 0 means allowed to stream | Y |
- | `msg` | `string` | Error message when streaming is not allowed | Y |
- | `enable_hls` | `bool` | Whether to convert to HLS-MPEGTS protocol | N |
- | `enable_hls_fmp4` | `bool` | Whether to convert to HLS-FMP4 protocol | N |
- | `enable_mp4` | `bool` | Whether to allow MP4 recording | N |
- | `enable_rtsp` | `bool` | Whether to convert to RTSP protocol | N |
- | `enable_rtmp` | `bool` | Whether to convert to RTMP/FLV protocol | N |
- | `enable_ts` | `bool` | Whether to convert to HTTP-TS/WS-TS protocol | N |
- | `enable_fmp4` | `bool` | Whether to convert to HTTP-FMP4/WS-FMP4 protocol | N |
- | `hls_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
- | `rtsp_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
- | `rtmp_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
- | `ts_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
- | `fmp4_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
- | `enable_audio` | `bool` | Whether to enable audio when converting protocols | N |
- | `add_mute_audio` | `bool` | Whether to add silent AAC audio when converting protocols | N |
- | `mp4_save_path` | `string` | Root directory for saving MP4 recording files, use default if empty | N |
- | `mp4_max_second` | `int` | MP4 recording segment size in seconds | N |
- | `mp4_as_player` | `bool` | Whether to count MP4 recording as viewers in playback count | N |
- | `hls_save_path` | `string` | Root directory for saving HLS files, use default if empty | N |
- | `modify_stamp` | `int` | Whether the stream enables timestamp overlay (0: absolute timestamp / 1: system timestamp / 2: relative timestamp) | N |
- | `continue_push_ms` | `uint32` | Delay in milliseconds for continuous reconnection, use default value from configuration file if empty | N |
- | `auto_close` | `bool` | Whether to automatically close the stream when no one is watching (without triggering the no-viewer hook) | N |
- | `stream_replace` | `string` | Whether to modify the stream ID, customizing thestream ID through this parameter (e.g., replacing SSRC) | N |
+ | Parameter Name | Parameter Type | Parameter Description | Required |
+ | :----------------: | :------------: | :----------------------------------------------------------------------------------------------------------------: | :------: |
+ | `code` | `int` | Error code, 0 means allowed to stream | Y |
+ | `msg` | `string` | Error message when streaming is not allowed | Y |
+ | `enable_hls` | `bool` | Whether to convert to HLS-MPEGTS protocol | N |
+ | `enable_hls_fmp4` | `bool` | Whether to convert to HLS-FMP4 protocol | N |
+ | `enable_mp4` | `bool` | Whether to allow MP4 recording | N |
+ | `enable_rtsp` | `bool` | Whether to convert to RTSP protocol | N |
+ | `enable_rtmp` | `bool` | Whether to convert to RTMP/FLV protocol | N |
+ | `enable_ts` | `bool` | Whether to convert to HTTP-TS/WS-TS protocol | N |
+ | `enable_fmp4` | `bool` | Whether to convert to HTTP-FMP4/WS-FMP4 protocol | N |
+ | `hls_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
+ | `rtsp_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
+ | `rtmp_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
+ | `ts_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
+ | `fmp4_demand` | `bool` | Whether the protocol generates only when someone is watching | N |
+ | `enable_audio` | `bool` | Whether to enable audio when converting protocols | N |
+ | `add_mute_audio` | `bool` | Whether to add silent AAC audio when converting protocols | N |
+ | `mp4_save_path` | `string` | Root directory for saving MP4 recording files, use default if empty | N |
+ | `mp4_max_second` | `int` | MP4 recording segment size in seconds | N |
+ | `mp4_as_player` | `bool` | Whether to count MP4 recording as viewers in playback count | N |
+ | `hls_save_path` | `string` | Root directory for saving HLS files, use default if empty | N |
+ | `modify_stamp` | `int` | Whether the stream enables timestamp overlay (0: absolute timestamp / 1: system timestamp / 2: relative timestamp) | N |
+ | `continue_push_ms` | `uint32` | Delay in milliseconds for continuous reconnection, use default value from configuration file if empty | N |
+ | `auto_close` | `bool` | Whether to automatically close the stream when no one is watching (without triggering the no-viewer hook) | N |
+ | `stream_replace` | `string` | Whether to modify the stream ID, customizing thestream ID through this parameter (e.g., replacing SSRC) | N |
+
### 8、on_record_mp4:
- Explanation:
@@ -409,7 +404,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -424,23 +419,23 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost" : "__defaultVhost__"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Description |
- | :------------: | :------------: | :----------------------------: |
- | `app` | `string` | Name of the recorded stream application |
- | `file_name` | `string` | File name |
- | `file_path` | `string` | Absolute file path |
- | `file_size` | `int` | File size in bytes |
- | `folder` | `string` | Directory path of the file |
- | `start_time` | `int` | Start time of the recording (timestamp) |
- | `stream` | `string` | Recorded stream ID |
- | `time_len` | `float` | Recording duration in seconds |
- | `url` | `string` | Relative URL path for http/rtsp/rtmp playback |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId`| `string` | Server ID set through the configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :------------: | :-------------------------------------------: |
+ | `app` | `string` | Name of the recorded stream application |
+ | `file_name` | `string` | File name |
+ | `file_path` | `string` | Absolute file path |
+ | `file_size` | `int` | File size in bytes |
+ | `folder` | `string` | Directory path of the file |
+ | `start_time` | `int` | Start time of the recording (timestamp) |
+ | `stream` | `string` | Recorded stream ID |
+ | `time_len` | `float` | Recording duration in seconds |
+ | `url` | `string` | Relative URL path for http/rtsp/rtmp playback |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID set through the configuration file |
+
- Default response:
```http
@@ -451,15 +446,12 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 07:53:13 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-
-
### 9、on_rtsp_realm:
@@ -479,7 +471,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -492,21 +484,21 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost" : "__defaultVhost__"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Description |
- | :------------: | :--------------: | :---------------------------: |
- | `app` | `string` | Stream application name |
- | `id` | `string` | Unique ID of the TCP connection |
- | `ip` | `string` | RTSP player IP address |
- | `params` | `string` | Parameters of the RTSP URL |
- | `port` | `unsigned short` | RTSP player port number |
- | `schema` | `string` | RTSP or RTSPS |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId`| `string` | Server ID set through the configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :-------------: | :--------------: | :------------------------------------------: |
+ | `app` | `string` | Stream application name |
+ | `id` | `string` | Unique ID of the TCP connection |
+ | `ip` | `string` | RTSP player IP address |
+ | `params` | `string` | Parameters of the RTSP URL |
+ | `port` | `unsigned short` | RTSP player port number |
+ | `schema` | `string` | RTSP or RTSPS |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID set through the configuration file |
+
- Default response:
```http
@@ -517,23 +509,20 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:05:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"realm" : "zlmediakit_reaml"
}
-
+
```
-
+
- Response parameter details:
- | Parameter Name | Parameter Type | Parameter Description |
- | :------------: | :------------: | :----------------------------------------------------: |
- | `code` | `int` | Please return 0 |
+ | Parameter Name | Parameter Type | Parameter Description |
+ | :------------: | :------------: | :--------------------------------------------------------------------------------------------------------------: |
+ | `code` | `int` | Please return 0 |
| `realm` | `string` | Whether the RTSP stream requires RTSP-specific authentication, an empty string means no authentication is needed |
-
-
-
### 10、on_rtsp_auth:
@@ -553,7 +542,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -568,26 +557,26 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"user_name" : "test",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :----------------: | :--------------: | :-----------------------------------------------------: |
- | `app` | `string` | Application name |
- | `id` | `string` | Unique ID for TCP connection |
- | `ip` | `string` | IP address of the RTSP player |
- | `must_no_encrypt` | `bool` | Indicates whether the requested password must be plaintext (Base64 authentication requires plaintext password) |
- | `params` | `string` | RTSP URL parameters |
- | `port` | `unsigned short` | Port number of the RTSP player |
- | `realm` | `string` | RTSP authentication encryption realm |
- | `schema` | `string` | RTSP or RTSPS |
- | `stream` | `string` | Stream ID |
- | `user_name` | `string` | Playback username |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId` | `string` | Server ID, set through the configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :---------------: | :--------------: | :------------------------------------------------------------------------------------------------------------: |
+ | `app` | `string` | Application name |
+ | `id` | `string` | Unique ID for TCP connection |
+ | `ip` | `string` | IP address of the RTSP player |
+ | `must_no_encrypt` | `bool` | Indicates whether the requested password must be plaintext (Base64 authentication requires plaintext password) |
+ | `params` | `string` | RTSP URL parameters |
+ | `port` | `unsigned short` | Port number of the RTSP player |
+ | `realm` | `string` | RTSP authentication encryption realm |
+ | `schema` | `string` | RTSP or RTSPS |
+ | `stream` | `string` | Stream ID |
+ | `user_name` | `string` | Playback username |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
+
- Default response:
```http
@@ -598,31 +587,29 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:05:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"encrypted" : false,
"passwd" : "test"
}
-
+
```
-
+
- Response parameter details:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :-------------: | :------------: | :------------------------------------------: |
- | `code` | `int` | Error code, 0 means allowed to play |
- | `msg` | `string` | Error message when playback authentication fails |
- | `encrypted` | `bool` | Indicates whether the user password is plaintext or digest |
- | `passwd` | `string` | User password plaintext or digest (md5(username:realm:password)) |
-
-
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :------------: | :------------: | :--------------------------------------------------------------: |
+ | `code` | `int` | Error code, 0 means allowed to play |
+ | `msg` | `string` | Error message when playback authentication fails |
+ | `encrypted` | `bool` | Indicates whether the user password is plaintext or digest |
+ | `passwd` | `string` | User password plaintext or digest (md5(username:realm:password)) |
### 11、on_shell_login:
- Explanation:
- Shell login authentication, ZLMediaKit provides a simple telnet debugging method. Use `telnet 127.0.0.1 9000` to access the shell interface of the MediaServer process.
+ Shell login authentication, ZLMediaKit provides a simple telnet debugging method. Use `telnet 127.0.0.1 9000` to access the shell interface of the MediaServer process.
- Trigger request:
@@ -636,7 +623,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"id" : "140227419332496",
@@ -646,18 +633,18 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"user_name" : "xzl"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :-------------: | :--------------: | :----------------------------: |
- | `id` | `string` | Unique ID for TCP connection |
- | `ip` | `string` | Telnet terminal IP |
- | `passwd` | `bool` | Telnet terminal login password |
- | `port` | `unsigned short` | Telnet terminal port number |
- | `user_name` | `string` | Telnet terminal login username |
- | `mediaServerId` | `string` | Server ID, set through the configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :--------------: | :-------------------------------------------: |
+ | `id` | `string` | Unique ID for TCP connection |
+ | `ip` | `string` | Telnet terminal IP |
+ | `passwd` | `bool` | Telnet terminal login password |
+ | `port` | `unsigned short` | Telnet terminal port number |
+ | `user_name` | `string` | Telnet terminal login username |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
+
- Default response:
```http
@@ -668,31 +655,30 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:23:00 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-- Response parameter details:
-
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :-----------: | :------------: | :---------------------------------------: |
- | `code` | `int` | Error code, 0 means allowed to login telnet |
- | `msg` | `string` | Error message when login telnet is not allowed |
-
+- Response parameter details:
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :------------: | :------------: | :--------------------------------------------: |
+ | `code` | `int` | Error code, 0 means allowed to login telnet |
+ | `msg` | `string` | Error message when login telnet is not allowed |
### 12、on_stream_changed:
- Explanation:
- This event is triggered when an RTSP/RTMP stream is registered or unregistered. This event does not require a response.
+ This event is triggered when an RTSP/RTMP stream is registered or unregistered. This event does not require a response.
- Trigger request:
+
- When unregistering:
+
```http
POST /index/hook/on_stream_changed HTTP/1.1
Accept: */*
@@ -703,7 +689,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -713,7 +699,9 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost" : "__defaultVhost__"
}
```
+
- When registering:
+
```http
POST /index/hook/on_stream_changed HTTP/1.1
Accept: */*
@@ -724,7 +712,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"regist" : true,
"aliveSecond": 0, # The time the stream remains alive, in seconds
@@ -749,7 +737,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"tracks": [{
"channels" : 1, # Number of audio channels
"codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # Codec type name
+ "codec_id_name" : "CodecAAC", # Codec type name
"codec_type" : 1, # Video = 0, Audio = 1
"ready" : true, # Whether the track is ready
"sample_bit" : 16, # Audio sample bit depth
@@ -757,7 +745,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
},
{
"codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # Codec type name
+ "codec_id_name" : "CodecH264", # Codec type name
"codec_type" : 0, # Video = 0, Audio = 1
"fps" : 59, # Video frames per second
"height" : 720, # video high
@@ -767,18 +755,18 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost": "__defaultVhost__"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :-------------: | :------------: | :----------------------------: |
- | `app` | `string` | Application name |
- | `regist` | `bool` | Stream registration or unregistration |
- | `schema` | `string` | RTSP or RTMP |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream virtual host |
- | `mediaServerId` | `string` | Server ID, set through the configuration file |
-
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :------------: | :-------------------------------------------: |
+ | `app` | `string` | Application name |
+ | `regist` | `bool` | Stream registration or unregistration |
+ | `schema` | `string` | RTSP or RTMP |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream virtual host |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
+
- Default response:
```http
@@ -789,28 +777,25 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:27:35 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-
-
### 13、on_stream_none_reader:
- Explanation:
- When there is no audience watching the stream, users can choose to close the stream without viewership through this event.
+ When there is no audience watching the stream, users can choose to close the stream without viewership through this event.
- If a live stream comes online and no one watches it, it will trigger an event of no viewership. The protocol schema triggered during this event is random and based on the latest registered protocol (usually HLS).
+ If a live stream comes online and no one watches it, it will trigger an event of no viewership. The protocol schema triggered during this event is random and based on the latest registered protocol (usually HLS).
When transitioning from viewership to no viewership, the protocol schema triggered will be the one used by the last viewer.
- Currently, MP4/HLS recordings are not considered as viewership. The MP4 recording can be controlled through the
- configuration file parameter "mp4_as_player," but RTSP/RTMP/RTP forwarding is counted as viewership and will also trigger this event.
+ Currently, MP4/HLS recordings are not considered as viewership. The MP4 recording can be controlled through the
+ configuration file parameter "mp4_as_player," but RTSP/RTMP/RTP forwarding is counted as viewership and will also trigger this event.
- Trigger request:
@@ -824,7 +809,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -833,16 +818,16 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost" : "__defaultVhost__"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :------------: | :------------: | :-------------------: |
- | `app` | `string` | Stream App Name |
- | `schema` | `string` | RTSP or RTMP |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream Virtual Host |
- | `mediaServerId` | `string` | Server ID, set through the configuration file |
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :------------: | :-------------------------------------------: |
+ | `app` | `string` | Stream App Name |
+ | `schema` | `string` | RTSP or RTMP |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream Virtual Host |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
- Default response:
@@ -854,28 +839,25 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:51:23 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"close" : true,
"code" : 0
}
```
-
-- Response parameter details:
-
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :------------: | :------------: | :-------------------: |
- | `code` | `int` | Please return 0 |
- | `close` | `bool` | Whether to close the stream or not |
-
+- Response parameter details:
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :------------: | :------------: | :--------------------------------: |
+ | `code` | `int` | Please return 0 |
+ | `close` | `bool` | Whether to close the stream or not |
### 14、on_stream_not_found:
- Explanation:
- When a stream is not found, users can immediately pull the stream when this event is triggered, allowing Pulling Streams on Demand. This event is not sensitive to replies.
+ When a stream is not found, users can immediately pull the stream when this event is triggered, allowing Pulling Streams on Demand. This event is not sensitive to replies.
- Trigger request:
@@ -889,7 +871,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -902,20 +884,20 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"vhost" : "__defaultVhost__"
}
```
-
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :------------: | :------------: | :-----------------------------: |
- | `app` | `string` | Stream App Name |
- | `id` | `string` | Unique TCP Connection ID |
- | `ip` | `string` | Player IP Address |
- | `params` | `string` | Player URL Parameters |
- | `port` | `unsigned short` | Player Port Number |
- | `schema` | `string` | Protocol for playback, possibly RTSP or RTMP |
- | `stream` | `string` | Stream ID |
- | `vhost` | `string` | Stream Virtual Host |
- | `mediaServerId`| `string` | Server ID, set through the configuration file |
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :--------------: | :-------------------------------------------: |
+ | `app` | `string` | Stream App Name |
+ | `id` | `string` | Unique TCP Connection ID |
+ | `ip` | `string` | Player IP Address |
+ | `params` | `string` | Player URL Parameters |
+ | `port` | `unsigned short` | Player Port Number |
+ | `schema` | `string` | Protocol for playback, possibly RTSP or RTMP |
+ | `stream` | `string` | Stream ID |
+ | `vhost` | `string` | Stream Virtual Host |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
- Default response:
@@ -927,20 +909,18 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:55:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success
}
```
-
-
-
### 15、on_server_started
+
- Explanation:
- Server startup event, can be used to monitor server crashes and restarts. This event is not sensitive to replies.
+ Server startup event, can be used to monitor server crashes and restarts. This event is not sensitive to replies.
- Trigger request:
@@ -954,7 +934,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"api.apiDebug" : "1",
"api.secret" : "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
@@ -1031,7 +1011,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
"shell.port" : "9000"
}
```
-
+
- Request parameters:
json object of configuration file
@@ -1045,7 +1025,7 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
Date: Fri, Sep 20 2019 08:55:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success
@@ -1056,77 +1036,80 @@ You can also refer to this [issue](https://github.com/zlmediakit/ZLMediaKit/issu
- Explanation:
- The server periodically reports time, which can be configured. The default interval is 10 seconds.
+ The server periodically reports time, which can be configured. The default interval is 10 seconds.
- Trigger request:
- ```http
- POST /index/hook/on_server_keepalive HTTP/1.1
- Accept: */*
- Accept-Language: zh-CN,zh;q=0.8
- Connection: keep-alive
- Content-Length: 189
- Content-Type: application/json
- Host: 127.0.0.1
- Tools: ZLMediaKit
- User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
- {
- "data" : {
- "Buffer" : 12,
- "BufferLikeString" : 0,
- "BufferList" : 0,
- "BufferRaw" : 12,
- "Frame" : 0,
- "FrameImp" : 0,
- "MediaSource" : 0,
- "MultiMediaSourceMuxer" : 0,
- "RtmpPacket" : 0,
- "RtpPacket" : 0,
- "Socket" : 108,
- "TcpClient" : 0,
- "TcpServer" : 96,
- "TcpSession" : 0,
- "UdpServer" : 12,
- "UdpSession" : 0
- },
- "mediaServerId" : "192.168.255.10"
- }
- ```
+ ```http
+ POST /index/hook/on_server_keepalive HTTP/1.1
+ Accept: */*
+ Accept-Language: zh-CN,zh;q=0.8
+ Connection: keep-alive
+ Content-Length: 189
+ Content-Type: application/json
+ Host: 127.0.0.1
+ Tools: ZLMediaKit
+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
+
+ {
+ "data" : {
+ "Buffer" : 12,
+ "BufferLikeString" : 0,
+ "BufferList" : 0,
+ "BufferRaw" : 12,
+ "Frame" : 0,
+ "FrameImp" : 0,
+ "MediaSource" : 0,
+ "MultiMediaSourceMuxer" : 0,
+ "RtmpPacket" : 0,
+ "RtpPacket" : 0,
+ "Socket" : 108,
+ "TcpClient" : 0,
+ "TcpServer" : 96,
+ "TcpSession" : 0,
+ "UdpServer" : 12,
+ "UdpSession" : 0
+ },
+ "mediaServerId" : "192.168.255.10"
+ }
+ ```
+
### 17、on_rtp_server_timeout
- Explanation:
- When calling the `openRtpServer` interface, if the RTP server does not receive data for a long time, this webhook will be executed. It is not sensitive to replies.
+ When calling the `openRtpServer` interface, if the RTP server does not receive data for a long time, this webhook will be executed. It is not sensitive to replies.
- 触发请求
- ```http
- POST /index/hook/on_rtp_server_timeout HTTP/1.1
- Accept: */*
- Accept-Language: zh-CN,zh;q=0.8
- Connection: keep-alive
- Content-Length: 189
- Content-Type: application/json
- Host: 127.0.0.1
- Tools: ZLMediaKit
- User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
- {
- "local_port" : 0,
- "re_use_port" : true,
- "ssrc" : 0,
- "stream_id" : "test",
- "tcp_mode" : 0,
- "mediaServerId" : "192.168.255.10"
- }
+ ```http
+ POST /index/hook/on_rtp_server_timeout HTTP/1.1
+ Accept: */*
+ Accept-Language: zh-CN,zh;q=0.8
+ Connection: keep-alive
+ Content-Length: 189
+ Content-Type: application/json
+ Host: 127.0.0.1
+ Tools: ZLMediaKit
+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
+
+ {
+ "local_port" : 0,
+ "re_use_port" : true,
+ "ssrc" : 0,
+ "stream_id" : "test",
+ "tcp_mode" : 0,
+ "mediaServerId" : "192.168.255.10"
+ }
+ ```
+
- Request parameters:
- | Parameter Name | Parameter Type | Parameter Explanation |
- | :------------: | :------------: | :-----------------------------: |
- | `local_port` | `int` | Parameter input for `openRtpServer` |
- | `re_use_port` | `bool` | Parameter input for `openRtpServer` |
- | `ssrc` | `uint32` | Parameter input for `openRtpServer` |
- | `stream_id` | `string` | Parameter input for `openRtpServer` |
- | `tcp_mode` | `int` | Parameter input for `openRtpServer` |
- | `mediaServerId`| `string` | Server ID, set through the configuration file |
+ | Parameter Name | Parameter Type | Parameter Explanation |
+ | :-------------: | :------------: | :-------------------------------------------: |
+ | `local_port` | `int` | Parameter input for `openRtpServer` |
+ | `re_use_port` | `bool` | Parameter input for `openRtpServer` |
+ | `ssrc` | `uint32` | Parameter input for `openRtpServer` |
+ | `stream_id` | `string` | Parameter input for `openRtpServer` |
+ | `tcp_mode` | `int` | Parameter input for `openRtpServer` |
+ | `mediaServerId` | `string` | Server ID, set through the configuration file |
diff --git a/src/guide/protocol/README.md b/src/guide/protocol/README.md
index 6ae16af..713c6e9 100644
--- a/src/guide/protocol/README.md
+++ b/src/guide/protocol/README.md
@@ -4,8 +4,4 @@ icon: lightbulb
index: false
---
-## Introduction
-
-We support foo feature, ...
-
-
+
diff --git a/src/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md b/src/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
index cd79461..cd02ad2 100644
--- a/src/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
+++ b/src/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
@@ -3,7 +3,9 @@ title: GB28181 SIP信令抓包
---
## 1、注册
+
- 注册请求:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK4162288924
@@ -18,7 +20,8 @@ Expires: 7200
Content-Length: 0
```
-- 回复401:
+- 回复 401:
+
```http
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK4162288924
@@ -33,6 +36,7 @@ Content-Length: 0
```
- 再次注册:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK3997518011
@@ -47,7 +51,9 @@ User-Agent: Hikvision
Expires: 7200
Content-Length: 0
```
+
- 注册成功:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK3997518011
@@ -61,9 +67,10 @@ Date: 2013-09-10T16:01:51
Content-Length: 0
```
-
## 2、注销
+
- 注销请求:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK1670314216
@@ -78,7 +85,8 @@ Expires: 0
Content-Length: 0
```
-- 回复401:
+- 回复 401:
+
```http
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK1670314216
@@ -93,6 +101,7 @@ Content-Length: 0
```
- 再次注销:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK317693249
@@ -109,6 +118,7 @@ Content-Length: 0
```
- 注销成功:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK317693249
@@ -122,9 +132,10 @@ Date: 2013-09-10T14:04:41
Content-Length: 0
```
-
## 3、心跳
+
- 请求:
+
```http
MESSAGE sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK2672759896
@@ -147,6 +158,7 @@ Content-Length: 150
```
- 回复:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK2672759896
@@ -158,9 +170,10 @@ User-Agent: Hikvision
Content-Length: 0
```
-
## 4、目录检索
+
- 请求:
+
```http
MESSAGE sip:130909113319427420@10.64.49.218:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.44:7100;rport;branch=z9hG4bK32925498
@@ -180,7 +193,9 @@ Content-Length: 124
130909113319427420
```
+
- 回复:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.44:7100;rport=7100;branch=z9hG4bK32925498
diff --git a/src/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md b/src/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
index ce88de8..778267a 100644
--- a/src/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
+++ b/src/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
@@ -1,24 +1,30 @@
---
title: GB28181怎么用设备ID作为流ID
---
-为了支持RTP流的识别(与摄像头ID产生关联), 必须通过 `源地址` 或 `ssrc` 或 `本地端口号` 来区分.
-但是在issue #338 里面有开发者反馈,有些设备不支持设置ssrc,ssrc一直为0.
+为了支持 RTP 流的识别(与摄像头 ID 产生关联), 必须通过 `源地址` 或 `ssrc` 或 `本地端口号` 来区分.
-而源地址端口也会一直变,RTP推流前SIP服务器也不知道摄像头推流端口(甚至IP都不知道) 那么区分流只通过源地址也不现实,
-因为一个局域网内也可能多个设备, 如果ZLMediaKit在公网,那么这些流的IP是一致的,而端口是随机的,根本没法跟摄像头ID对应起来.
+但是在 issue #338 里面有开发者反馈,有些设备不支持设置 ssrc,ssrc 一直为 0.
-所以为了实现RTP推流参数的流ID与摄像头ID产生关联,就基本只剩下`本地端口号`这条路了,这就意味着一个端口只能接受一个流。
+而源地址端口也会一直变,RTP 推流前 SIP 服务器也不知道摄像头推流端口(甚至 IP 都不知道) 那么区分流只通过源地址也不现实,
+因为一个局域网内也可能多个设备, 如果 ZLMediaKit 在公网,那么这些流的 IP 是一致的,而端口是随机的,根本没法跟摄像头 ID 对应起来.
-在不指定流ID时,ZLMediaKit的行为跟之前完全一样,单端口支持多流,ssrc作为stream id。
+所以为了实现 RTP 推流参数的流 ID 与摄像头 ID 产生关联,就基本只剩下`本地端口号`这条路了,这就意味着一个端口只能接受一个流。
-如果指定了该端口绑定的流ID,那么该端口只能接收一路流。
+在不指定流 ID 时,ZLMediaKit 的行为跟之前完全一样,单端口支持多流,ssrc 作为 stream id。
+
+如果指定了该端口绑定的流 ID,那么该端口只能接收一路流。
以下是关键代码:
+
![image](/images/how_to_use_device_id_as_stream_id_1.png)
+
![image](/images/how_to_use_device_id_as_stream_id_2.png)
+
![image](/images/how_to_use_device_id_as_stream_id_3.png)
+
![image](/images/how_to_use_device_id_as_stream_id_4.png)
+
![image](/images/how_to_use_device_id_as_stream_id_5.png)
-![image](/images/how_to_use_device_id_as_stream_id_6.png)
+![image](/images/how_to_use_device_id_as_stream_id_6.png)
diff --git a/src/guide/protocol/gb28181/push_streaming.md b/src/guide/protocol/gb28181/push_streaming.md
index 1ed2c0f..7744b5a 100644
--- a/src/guide/protocol/gb28181/push_streaming.md
+++ b/src/guide/protocol/gb28181/push_streaming.md
@@ -1,91 +1,99 @@
---
title: GB28181推流
---
+
## 介绍
-ZLMediaKit支持GB28181的 ps-rtp推流,支持的编码格式分别为 `h264/h265/aac/g711/opus`。
-在收到GB28181推流后,ZLMediaKit会依次做以下事情:
-- rtp排序去重。
-- rtp解析成ps或ts。
-- ps或ts解析成`h264/h265/aac/g711/opus`。
-- 输入到复用器,生成rtsp/rtmp/ts/fmp4等格式,以便转换成其他协议或容器。
+ZLMediaKit 支持 GB28181 的 ps-rtp 推流,支持的编码格式分别为 `h264/h265/aac/g711/opus`。
+在收到 GB28181 推流后,ZLMediaKit 会依次做以下事情:
+
+- rtp 排序去重。
+- rtp 解析成 ps 或 ts。
+- ps 或 ts 解析成`h264/h265/aac/g711/opus`。
+- 输入到复用器,生成 rtsp/rtmp/ts/fmp4 等格式,以便转换成其他协议或容器。
## 简单使用
-ZLMediaKit默认开启10000端口用于接收UDP/TCP的GB28181推流,由于国标推流不好测试,ZLMediaKit同时也支持rtp_mpegts推流,代码会自适应判断是否为ps还是ts。
-所以如果大家没有摄像头的情况下,可以用FFmpeg简单测试,基本上体验跟国标推流并无二致。
-- ffmpeg推流命令:
-```bash
- ffmpeg -re -i www/record/robot.mp4 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
-```
+ZLMediaKit 默认开启 10000 端口用于接收 UDP/TCP 的 GB28181 推流,由于国标推流不好测试,ZLMediaKit 同时也支持 rtp_mpegts 推流,代码会自适应判断是否为 ps 还是 ts。
+所以如果大家没有摄像头的情况下,可以用 FFmpeg 简单测试,基本上体验跟国标推流并无二致。
+
+- ffmpeg 推流命令:
+
+ ```bash
+ ffmpeg -re -i www/record/robot.mp4 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
+ ```
-- MediaServer收到推流后的日志:
-![图片](/images/gb28181_push_streaming_1.png)
+- MediaServer 收到推流后的日志:
-上图中,这个推流的rtp ssrc为BFC2C622(16进制打印),这个流的app为`rtp`, stream_id为`BFC2C622`,您可以根据[wiki](../../media_server/play_url_rules.md)来组合成url并播放这个流。
+ ![图片](/images/gb28181_push_streaming_1.png)
-需要指出的是,国标推流的app固定为rtp,你只能通过代码来修改它,stream_id为rtp流的ssrc,这个是随机的,在FFmpeg中貌似没法控制。
+ 上图中,这个推流的 rtp ssrc 为 BFC2C622(16 进制打印),这个流的 app 为`rtp`, stream_id 为`BFC2C622`,您可以根据[wiki](../../media_server/play_url_rules.md)来组合成 url 并播放这个流。
-另外,每次推流时,请更换ssrc,否则ZLMediaKit发现推流端ip和端口变化后,会直接丢弃rtp包(现象如此[issue](https://github.com/xia-chu/ZLMediaKit/issues/267));这样做的目的是为了防止两个设备使用同一个ssrc推流时互相干扰。
+需要指出的是,国标推流的 app 固定为 rtp,你只能通过代码来修改它,stream_id 为 rtp 流的 ssrc,这个是随机的,在 FFmpeg 中貌似没法控制。
+另外,每次推流时,请更换 ssrc,否则 ZLMediaKit 发现推流端 ip 和端口变化后,会直接丢弃 rtp 包(现象如此[issue](https://github.com/xia-chu/ZLMediaKit/issues/267));这样做的目的是为了防止两个设备使用同一个 ssrc 推流时互相干扰。
## 高阶使用
-在推流给10000端口时,您可能发现有个缺陷,就是stream_id是ssrc,比较抽象,可能还没法控制。
-那么我们能否自定义stream_id? 答案是肯定的,ZLMediaKit通过[restful api](../../media_server/restful_api.md#24indexapiopenrtpserver)可以动态开启国标收流端口(同时支持udp/tcp模式)。
+在推流给 10000 端口时,您可能发现有个缺陷,就是 stream_id 是 ssrc,比较抽象,可能还没法控制。
-在使用openRtpServer接口动态开启国标收流端口后,这个端口只能产生一个流,也就是说,一个摄像头需要一个服务器端口用于接收国标推流。
+那么我们能否自定义 stream_id? 答案是肯定的,ZLMediaKit 通过[restful api](../../media_server/restful_api.md#24indexapiopenrtpserver)可以动态开启国标收流端口(同时支持 udp/tcp 模式)。
-- 以下是演示范例(postman工具调用openRtpServer接口创建随机端口):
+在使用 openRtpServer 接口动态开启国标收流端口后,这个端口只能产生一个流,也就是说,一个摄像头需要一个服务器端口用于接收国标推流。
-
+- 以下是演示范例(postman 工具调用 openRtpServer 接口创建随机端口):
+
+![图片](https://user-images.githubusercontent.com/11495632/93871851-e232dc00-fd01-11ea-8802-b8e91e5f6de1.png =1631x)
+
+- 然后启动 FFmpeg 推流
-- 然后启动FFmpeg推流
```bash
ffmpeg -re -i www/record/robot.mp4 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:50077
```
- 以下是推流后注册的服务器日志
-![图片](/images/gb28181_push_streaming_2.png)
-- 需要指出的是,如果openRtpServer接口创建的端口一直没收到流(或者解析不出流),那么会自动关闭和释放。
+ ![图片](/images/gb28181_push_streaming_2.png)
+- 需要指出的是,如果 openRtpServer 接口创建的端口一直没收到流(或者解析不出流),那么会自动关闭和释放。
## 调试文件生成
-如果你的MediaServer能收到国标推流,但是未出现`媒体注册`相关日志,那么有可能是流有些异常,你可以修改配置文件`rtp_proxy.dumpDir`指定调试文件导出目录,
-这样ZLMediaKit会把国标流导出到该文件夹,就像这样:
-
+如果你的 MediaServer 能收到国标推流,但是未出现`媒体注册`相关日志,那么有可能是流有些异常,你可以修改配置文件`rtp_proxy.dumpDir`指定调试文件导出目录,
+这样 ZLMediaKit 会把国标流导出到该文件夹,就像这样:
-你可以直接用ffplay播放`mp2/video后缀的文件`,`rtp`后缀的文件,你可以用测试工具`test_rtp`调试,或者你可以把它分享给其他人帮你分析原因。
+![图片](https://user-images.githubusercontent.com/11495632/93872911-6c2f7480-fd03-11ea-85d4-911d6d998c83.png =611x)
+你可以直接用 ffplay 播放`mp2/video后缀的文件`,`rtp`后缀的文件,你可以用测试工具`test_rtp`调试,或者你可以把它分享给其他人帮你分析原因。
-## 让ZLMediaKit往其他国标服务器推流
-你可以使用[restful api](../../media_server/restful_api.md#27indexapistartsendrtp)让ZLMediaKit生成国标流并往其他服务器推送,支持其他任何已注册的流转国标流。
+## 让 ZLMediaKit 往其他国标服务器推流
-- postman调用startSendRtp接口推送国标流:
+你可以使用[restful api](../../media_server/restful_api.md#27indexapistartsendrtp)让 ZLMediaKit 生成国标流并往其他服务器推送,支持其他任何已注册的流转国标流。
-
+- postman 调用 startSendRtp 接口推送国标流:
-![图片](/images/gb28181_push_streaming_3.png)
+![图片](https://user-images.githubusercontent.com/11495632/93873636-a0576500-fd04-11ea-8b0f-98fb3f60c778.png =1551x)
+![图片](/images/gb28181_push_streaming_3.png)
-- 上图中是推送国标流给自己,当然你也可以推送给其他服务器,支持udp/tcp方式推流。
+- 上图中是推送国标流给自己,当然你也可以推送给其他服务器,支持 udp/tcp 方式推流。
## 性能
-GB28181的推流性能测试,请参考:[#961](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
+
+GB28181 的推流性能测试,请参考:[#961](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
## 丢包问题调试
-如果在测试GB28181 UDP推流时,频繁打印以下日志:
+
+如果在测试 GB28181 UDP 推流时,频繁打印以下日志:
![图片](/images/gb28181_push_streaming_4.png)
-请查看此[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/1221),特别提示,wifi情况下,由于无线网络干扰严重,丢包问题很可能确实是网络质量差导致的。
+请查看此[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/1221),特别提示,wifi 情况下,由于无线网络干扰严重,丢包问题很可能确实是网络质量差导致的。
## 相关文章推荐阅读
-[WVP+ZLMediaKit+MediaServerUI实现摄像头GB28181推流播放录制 ](https://notemi.cn/wvp---zlmedia-kit---mediaserverui-to-realize-streaming-playback-and-recording-of-camera-gb28181.html)
-[使用 GB28181.Solution + ZLMediaKit + MediaServerUI 进行摄像头推流和播放](http://dlgcy.com/gb28181-solution-zlmediakit-mediaserverui/)
+- [WVP+ZLMediaKit+MediaServerUI 实现摄像头 GB28181 推流播放录制](https://notemi.cn/wvp---zlmedia-kit---mediaserverui-to-realize-streaming-playback-and-recording-of-camera-gb28181.html)
-[GB28181语音对讲](https://github.com/ZLMediaKit/ZLMediaKit/issues/2217)
+- [使用 GB28181.Solution + ZLMediaKit + MediaServerUI 进行摄像头推流和播放](http://dlgcy.com/gb28181-solution-zlmediakit-mediaserverui/)
+- [GB28181 语音对讲](https://github.com/ZLMediaKit/ZLMediaKit/issues/2217)
diff --git a/src/guide/protocol/srt/README.md b/src/guide/protocol/srt/README.md
index 3aa048e..32538a4 100644
--- a/src/guide/protocol/srt/README.md
+++ b/src/guide/protocol/srt/README.md
@@ -3,47 +3,46 @@ title: SRT
---
## feature
+
- NACK support
- listener support
- push stream payload must ts
- pull stream payload is ts
-- protocol impliment [reference](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html)
+- protocol implement [reference](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html)
- version support (>=1.3.0)
-- fec and encriyped not support
+- fec and encrypted not support
-## usage
+## usage
-zlm get vhost,app,streamid and push or play by streamid of srt like this
-`#!::key1=value1,key2=value2,key3=value4......`
+zlm get vhost,app,streamid and push or play by streamid of srt like this `#!::key1=value1,key2=value2,key3=value4......`
h and r is special key,to get vhost app streamid, if h not exist ,vhost is default value
-m is special key, to judge is push or pull, if vaule is publish the mode is push,otherwise is play, if m not exist, mode is play
+m is special key, to judge is push or pull, if value is publish the mode is push,otherwise is play, if m not exist, mode is play
other key and m ,can use by webhook to auth for play or push
-
like:
- #!::h=zlmediakit.com,r=live/test,m=publish
+#!::h=zlmediakit.com,r=live/test,m=publish
- vhost = zlmediakit.com
+vhost = zlmediakit.com
- app = live
+app = live
- streamid = test
+streamid = test
- mode is push
+mode is push
- OBS push stream url
- `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
-- ffmpeg push
+ `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
- `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
-- ffplay pull
+- ffmpeg push
- `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test`
+ `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
-- vlc not support ,because can't set stream id [reference](https://github.com/Haivision/srt/issues/1015)
+- ffplay pull
+ `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test`
+- vlc not support ,because can't set stream id [reference](https://github.com/Haivision/srt/issues/1015)
diff --git a/src/guide/protocol/webrtc/webrtc_compilation_and_use.md b/src/guide/protocol/webrtc/webrtc_compilation_and_use.md
index a4896e6..27136cd 100644
--- a/src/guide/protocol/webrtc/webrtc_compilation_and_use.md
+++ b/src/guide/protocol/webrtc/webrtc_compilation_and_use.md
@@ -15,74 +15,78 @@ cmake version 3.20.5
- Install OpenSSL (version 1.1 or above)
- ```shell
- $ wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
- $ tar -xvzf openssl-1.1.1k.tar.gz
- $ yum install -y zlib zlib-devel perl-CPAN
- $ ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl
- $ make && make install
- $ echo "/usr/local/lib64/" >> /etc/ld.so.conf
- $ echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
- $ ldconfig
- $ ln -s /usr/local/openssl/bin/openssl /usr/local/bin/openssl # 替换系统openssl,非必须
- $ openssl version -a
- ```
+ ```shell
+ $ wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
+ $ tar -xvzf openssl-1.1.1k.tar.gz
+ $ yum install -y zlib zlib-devel perl-CPAN
+ $ ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl
+ $ make && make install
+ $ echo "/usr/local/lib64/" >> /etc/ld.so.conf
+ $ echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
+ $ ldconfig
+ $ ln -s /usr/local/openssl/bin/openssl /usr/local/bin/openssl # 替换系统openssl,非必须
+ $ openssl version -a
+ ```
- Install libsrtp
- Click [here](https://codeload.github.com/cisco/libsrtp/tar.gz/refs/tags/v2.3.0) to download and install.
+ Click [here](https://codeload.github.com/cisco/libsrtp/tar.gz/refs/tags/v2.3.0) to download and install.
- ```shell
- $ tar -xvzf libsrtp-2.3.0.tar.gz
- $ cd libsrtp-2.3.0
- $ ./configure --enable-openssl --with-openssl-dir=/usr/local/openssl
- $ make -j8 && make install
- ```
+ ```shell
+ $ tar -xvzf libsrtp-2.3.0.tar.gz
+ $ cd libsrtp-2.3.0
+ $ ./configure --enable-openssl --with-openssl-dir=/usr/local/openssl
+ $ make -j8 && make install
+ ```
- For some newer compilation environments (such as GCC 10+), there may be issues when compiling libsrtp-2.3.0. You can consider switching to version 2.5.0 as follows:
- ```
- $ wget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz
- $ tar -xvzf libsrtp-2.5.0.tar.gz
- $ cd libsrtp-2.5.0
- ```
+ For some newer compilation environments (such as GCC 10+), there may be issues when compiling libsrtp-2.3.0. You can consider switching to version 2.5.0 as follows:
+
+ ```sh
+ $ wget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz
+ $ tar -xvzf libsrtp-2.5.0.tar.gz
+ $ cd libsrtp-2.5.0
+ ```
## Compilation
- Download ZLMediaKit source code
- ```shell
- # Chinese users are recommended to download from the mirror site gitee
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- # Do not forget to execute this command
- git submodule update --init
- ```
+ ```shell
+ # Chinese users are recommended to download from the mirror site gitee
+ git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+ cd ZLMediaKit
+ # Do not forget to execute this command
+ git submodule update --init
+ ```
- Compilation
- ```shell
- $ mkdir build
- $ cd build
- $ cmake .. -DENABLE_WEBRTC=true -DOPENSSL_ROOT_DIR=/usr/local/openssl -DOPENSSL_LIBRARIES=/usr/local/openssl/lib
- $ cmake --build . --target MediaServer
-
- # final result
- [ 96%] Built target test_rtcp_fci
- [ 96%] Building CXX object tests/CMakeFiles/test_rtp.dir/test_rtp.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_rtp
- [ 97%] Built target test_rtp
- [ 97%] Building CXX object tests/CMakeFiles/test_wsServer.dir/test_wsServer.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_wsServer
- [ 97%] Built target test_wsServer
- [ 97%] Building CXX object tests/CMakeFiles/test_server.dir/test_server.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_server
- [ 97%] Built target test_server
- [ 98%] Built target jsoncpp
- [ 98%] Linking CXX executable ../../release/linux/Debug/MediaServer
- [100%] Built target MediaServer
- ```
+ ```shell
+ $ mkdir build
+ $ cd build
+ $ cmake .. -DENABLE_WEBRTC=true -DOPENSSL_ROOT_DIR=/usr/local/openssl -DOPENSSL_LIBRARIES=/usr/local/openssl/lib
+ $ cmake --build . --target MediaServer
+
+ # final result
+ [ 96%] Built target test_rtcp_fci
+ [ 96%] Building CXX object tests/CMakeFiles/test_rtp.dir/test_rtp.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_rtp
+ [ 97%] Built target test_rtp
+ [ 97%] Building CXX object tests/CMakeFiles/test_wsServer.dir/test_wsServer.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_wsServer
+ [ 97%] Built target test_wsServer
+ [ 97%] Building CXX object tests/CMakeFiles/test_server.dir/test_server.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_server
+ [ 97%] Built target test_server
+ [ 98%] Built target jsoncpp
+ [ 98%] Linking CXX executable ../../release/linux/Debug/MediaServer
+ [100%] Built target MediaServer
+ ```
+
## Modify Configuration File
+
Since WebRTC protocol requires informing the player of the server's IP address, if the IP address is not visible to the player, WebRTC communication will fail. Please modify the `rtc.externIP` configuration item in the configuration file to the visible IP address of the player. If this configuration item is not set, zlmediakit will retrieve the IP address of the network card (usually an internal IP address), which will prevent cross-domain NAT usage of WebRTC.
+
```ini
[rtc]
# Timeout for RTC streaming and playback
@@ -105,10 +109,11 @@ The latest zlmediakit source code comes with a valid SSL certificate `default.pe
- Error message: `gmake[3]: *** No rule to make target `/usr/lib64/libssl.so', needed by `../release/linux/Debug/MediaServer'. Stop.`
- ```
- cd /usr/local/openssl/lib
- cp -r ./* /usr/lib64/
- ```
+ ```sh
+ cd /usr/local/openssl/lib
+ cp -r ./* /usr/lib64/
+ ```
+
- Compilation on Ubuntu
You can refer to this [blog post](https://blog.csdn.net/haysonzeng/article/details/116754065) written by a skilled user.
@@ -119,6 +124,7 @@ The latest zlmediakit source code comes with a valid SSL certificate `default.pe
Also, refer to [this comment](https://github.com/ZLMediaKit/ZLMediaKit/issues/1081#issuecomment-910141630).
## Q&A(Playback Issues) ?
+
- OBS streaming and RTC playback stuttering?
WebRTC H.264 does not support B-frames, so B-frames need to be removed when using FFmpeg. You can add the `-bf 0` parameter or specify the H.264 profile as baseline.
@@ -129,4 +135,4 @@ The latest zlmediakit source code comes with a valid SSL certificate `default.pe
- WebRTC video or audio not playing?
- WebRTC in the web client supports encoding formats such as H.264, opus/48000/2, pcma/8000, pcmu/8000. Check if the encoding format is correct. Usually, theaudio is not supported, and you need to use the transcode branch for transcoding (video does not require transcoding).
+ WebRTC in the web client supports encoding formats such as H.264, opus/48000/2, pcma/8000, pcmu/8000. Check if the encoding format is correct. Usually, the audio is not supported, and you need to use the transcode branch for transcoding (video does not require transcoding).
diff --git a/src/guide/protocol/webrtc/webrtc_signaling_interaction_format.md b/src/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
index f6b2c07..b0d6b2b 100644
--- a/src/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
+++ b/src/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
@@ -1,7 +1,9 @@
---
title: WebRTC Signaling Interaction Format
---
+
## Introduction
+
zlmediakit has added support for the whip/whep standard in the WebRTC signaling format. The test url are as follows:
Push stream:https://zlmediakit.com/index/api/whip?app=live&stream=test
@@ -15,145 +17,147 @@ The subsequent sections of this article will cover the private signaling format.
- Request URL: /index/api/webrtc?app=live&stream=test&type=[push/play/echo]
- Request Method: HTTP POST
- Request Body: WebRTC offer SDP
-- Response Body:
-```json
-{
- "code" : 0,
- "id" : "zlm_1",
- "sdp" : "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
- "type" : "answer"
-}
-```
+- Response Body:
+
+ ```json
+ {
+ "code": 0,
+ "id": "zlm_1",
+ "sdp": "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
+ "type": "answer"
+ }
+ ```
## 2. Supported Type Types
+
- push: WebRTC streaming
- play: WebRTC playback
- echo: WebRTC mirroring and echo (only for WebRTC bidirectional testing)
- Users can develop and register additional type plugins for customization.
## 3. Example
+
- Request:
-```http
-POST /index/api/webrtc?app=live&stream=test&type=push HTTP/1.1
-Host: 127.0.0.1:8080
-User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/111.0
-Accept: application/json, text/plain, */*
-Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
-Accept-Encoding: gzip, deflate, br
-Content-Type: text/plain;charset=utf-8
-Content-Length: 2654
-Origin: http://127.0.0.1:8080
-Connection: keep-alive
-Referer: http://127.0.0.1:8080/webrtc/
-Cookie: ZL_COOKIE=45bcd71af9fbfa8fe576d1ef3f42ef69
-Sec-Fetch-Dest: empty
-Sec-Fetch-Mode: cors
-Sec-Fetch-Site: same-origin
-
-v=0
-o=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 0.0.0.0
-s=-
-t=0 0
-a=fingerprint:sha-256 10:09:E1:DB:B6:2D:58:ED:B3:7A:7A:B7:77:34:64:06:65:E7:5F:F2:CB:B5:BA:1A:C5:7C:A6:F5:8C:29:45:E0
-a=group:BUNDLE 0 1
-a=ice-options:trickle
-a=msid-semantic:WMS *
-m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
-c=IN IP4 0.0.0.0
-a=sendrecv
-a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
-a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level
-a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
-a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
-a=fmtp:101 0-15
-a=ice-pwd:e4efb3b86c1b7e1cb8fd949db7796641
-a=ice-ufrag:24ab201c
-a=mid:0
-a=msid:- {2320d86d-4e2f-4c3f-a378-b9e701dceeae}
-a=rtcp-mux
-a=rtpmap:109 opus/48000/2
-a=rtpmap:9 G722/8000/1
-a=rtpmap:0 PCMU/8000
-a=rtpmap:8 PCMA/8000
-a=rtpmap:101 telephone-event/8000/1
-a=setup:actpass
-a=ssrc:1347702353 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
-m=video 9 UDP/TLS/RTP/SAVPF 120 124 121 125 126 127 97 98
-c=IN IP4 0.0.0.0
-a=sendrecv
-a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
-a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
-a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
-a=extmap:6/recvonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
-a=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
-a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
-a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
-a=fmtp:120 max-fs=12288;max-fr=60
-a=fmtp:124 apt=120
-a=fmtp:121 max-fs=12288;max-fr=60
-a=fmtp:125 apt=121
-a=fmtp:127 apt=126
-a=fmtp:98 apt=97
-a=ice-pwd:e4efb3b86c1b7e1cb8fd949db7796641
-a=ice-ufrag:24ab201c
-a=mid:1
-a=msid:- {270d6bf9-cf47-4e3f-9bb5-e9bf7143ea4a}
-a=rtcp-fb:120 nack
-a=rtcp-fb:120 nack pli
-a=rtcp-fb:120 ccm fir
-a=rtcp-fb:120 goog-remb
-a=rtcp-fb:120 transport-cc
-a=rtcp-fb:121 nack
-a=rtcp-fb:121 nack pli
-a=rtcp-fb:121 ccm fir
-a=rtcp-fb:121 goog-remb
-a=rtcp-fb:121 transport-cc
-a=rtcp-fb:126 nack
-a=rtcp-fb:126 nack pli
-a=rtcp-fb:126 ccm fir
-a=rtcp-fb:126 goog-remb
-a=rtcp-fb:126 transport-cc
-a=rtcp-fb:97 nack
-a=rtcp-fb:97 nack pli
-a=rtcp-fb:97 ccm fir
-a=rtcp-fb:97 goog-remb
-a=rtcp-fb:97 transport-cc
-a=rtcp-mux
-a=rtcp-rsize
-a=rtpmap:120 VP8/90000
-a=rtpmap:124 rtx/90000
-a=rtpmap:121 VP9/90000
-a=rtpmap:125 rtx/90000
-a=rtpmap:126 H264/90000
-a=rtpmap:127 rtx/90000
-a=rtpmap:97 H264/90000
-a=rtpmap:98 rtx/90000
-a=setup:actpass
-a=ssrc:3676200744 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
-a=ssrc:3937745592 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
-a=ssrc-group:FID 3676200744 3937745592
-```
-- Response:
-```http
-HTTP/1.1 200 OK
-Access-Control-Allow-Credentials: true
-Access-Control-Allow-Origin: *
-Connection: keep-alive
-Content-Length: 1923
-Content-Type: application/json
-Date: Wed, Mar 29 2023 12:43:08 GMT
-Keep-Alive: timeout=30, max=100
-Server: ZLMediaKit(git hash:500d2c6a/2023-03-14T17:33:46+08:00,branch:master,build time:2023-03-15T15:03:55)
+ ```http
+ POST /index/api/webrtc?app=live&stream=test&type=push HTTP/1.1
+ Host: 127.0.0.1:8080
+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/111.0
+ Accept: application/json, text/plain, */*
+ Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
+ Accept-Encoding: gzip, deflate, br
+ Content-Type: text/plain;charset=utf-8
+ Content-Length: 2654
+ Origin: http://127.0.0.1:8080
+ Connection: keep-alive
+ Referer: http://127.0.0.1:8080/webrtc/
+ Cookie: ZL_COOKIE=45bcd71af9fbfa8fe576d1ef3f42ef69
+ Sec-Fetch-Dest: empty
+ Sec-Fetch-Mode: cors
+ Sec-Fetch-Site: same-origin
-{
- "code" : 0,
- "id" : "zlm_1",
- "sdp" : "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
- "type" : "answer"
-}
+ v=0
+ o=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 0.0.0.0
+ s=-
+ t=0 0
+ a=fingerprint:sha-256 10:09:E1:DB:B6:2D:58:ED:B3:7A:7A:B7:77:34:64:06:65:E7:5F:F2:CB:B5:BA:1A:C5:7C:A6:F5:8C:29:45:E0
+ a=group:BUNDLE 0 1
+ a=ice-options:trickle
+ a=msid-semantic:WMS *
+ m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8 101
+ c=IN IP4 0.0.0.0
+ a=sendrecv
+ a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+ a=extmap:2/recvonly urn:ietf:params:rtp-hdrext:csrc-audio-level
+ a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
+ a=fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1
+ a=fmtp:101 0-15
+ a=ice-pwd:e4efb3b86c1b7e1cb8fd949db7796641
+ a=ice-ufrag:24ab201c
+ a=mid:0
+ a=msid:- {2320d86d-4e2f-4c3f-a378-b9e701dceeae}
+ a=rtcp-mux
+ a=rtpmap:109 opus/48000/2
+ a=rtpmap:9 G722/8000/1
+ a=rtpmap:0 PCMU/8000
+ a=rtpmap:8 PCMA/8000
+ a=rtpmap:101 telephone-event/8000/1
+ a=setup:actpass
+ a=ssrc:1347702353 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
+ m=video 9 UDP/TLS/RTP/SAVPF 120 124 121 125 126 127 97 98
+ c=IN IP4 0.0.0.0
+ a=sendrecv
+ a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
+ a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+ a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
+ a=extmap:6/recvonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
+ a=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
+ a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
+ a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
+ a=fmtp:120 max-fs=12288;max-fr=60
+ a=fmtp:124 apt=120
+ a=fmtp:121 max-fs=12288;max-fr=60
+ a=fmtp:125 apt=121
+ a=fmtp:127 apt=126
+ a=fmtp:98 apt=97
+ a=ice-pwd:e4efb3b86c1b7e1cb8fd949db7796641
+ a=ice-ufrag:24ab201c
+ a=mid:1
+ a=msid:- {270d6bf9-cf47-4e3f-9bb5-e9bf7143ea4a}
+ a=rtcp-fb:120 nack
+ a=rtcp-fb:120 nack pli
+ a=rtcp-fb:120 ccm fir
+ a=rtcp-fb:120 goog-remb
+ a=rtcp-fb:120 transport-cc
+ a=rtcp-fb:121 nack
+ a=rtcp-fb:121 nack pli
+ a=rtcp-fb:121 ccm fir
+ a=rtcp-fb:121 goog-remb
+ a=rtcp-fb:121 transport-cc
+ a=rtcp-fb:126 nack
+ a=rtcp-fb:126 nack pli
+ a=rtcp-fb:126 ccm fir
+ a=rtcp-fb:126 goog-remb
+ a=rtcp-fb:126 transport-cc
+ a=rtcp-fb:97 nack
+ a=rtcp-fb:97 nack pli
+ a=rtcp-fb:97 ccm fir
+ a=rtcp-fb:97 goog-remb
+ a=rtcp-fb:97 transport-cc
+ a=rtcp-mux
+ a=rtcp-rsize
+ a=rtpmap:120 VP8/90000
+ a=rtpmap:124 rtx/90000
+ a=rtpmap:121 VP9/90000
+ a=rtpmap:125 rtx/90000
+ a=rtpmap:126 H264/90000
+ a=rtpmap:127 rtx/90000
+ a=rtpmap:97 H264/90000
+ a=rtpmap:98 rtx/90000
+ a=setup:actpass
+ a=ssrc:3676200744 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
+ a=ssrc:3937745592 cname:{e94c5049-fb95-4bd6-b2d1-221cd51b713f}
+ a=ssrc-group:FID 3676200744 3937745592
+ ```
-```
+- Response:
+ ```http
+ HTTP/1.1 200 OK
+ Access-Control-Allow-Credentials: true
+ Access-Control-Allow-Origin: *
+ Connection: keep-alive
+ Content-Length: 1923
+ Content-Type: application/json
+ Date: Wed, Mar 29 2023 12:43:08 GMT
+ Keep-Alive: timeout=30, max=100
+ Server: ZLMediaKit(git hash:500d2c6a/2023-03-14T17:33:46+08:00,branch:master,build time:2023-03-15T15:03:55)
+ {
+ "code" : 0,
+ "id" : "zlm_1",
+ "sdp" : "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
+ "type" : "answer"
+ }
+ ```
diff --git a/src/guide/sdk/README.md b/src/guide/sdk/README.md
index d2fd4ee..bddecef 100644
--- a/src/guide/sdk/README.md
+++ b/src/guide/sdk/README.md
@@ -3,6 +3,4 @@ title: SDK API
icon: lightbulb
---
-## Introduction
-
-We support foo feature, ...
+
diff --git a/src/more/collaborative_projects.md b/src/more/collaborative_projects.md
index 8dfe72b..d18f52c 100644
--- a/src/more/collaborative_projects.md
+++ b/src/more/collaborative_projects.md
@@ -4,12 +4,14 @@ icon: circle-info
---
- Visual management website
- - [The latest web project with front-end and back-end separation, supporting webrtc playback](https://github.com/langmansh/AKStreamNVR)
- - [Management web site based on ZLMediaKit master branch](https://gitee.com/kkkkk5G/MediaServerUI)
- - [Management web site based on ZLMediaKit branch](https://github.com/chenxiaolei/ZLMediaKit_NVR_UI)
- - [A very beautiful visual background management system](https://github.com/MingZhuLiu/ZLMediaServerManagent)
-
+
+ - [The latest web project with front-end and back-end separation, supporting webrtc playback](https://github.com/langmansh/AKStreamNVR)
+ - [Management web site based on ZLMediaKit master branch](https://gitee.com/kkkkk5G/MediaServerUI)
+ - [Management web site based on ZLMediaKit branch](https://github.com/chenxiaolei/ZLMediaKit_NVR_UI)
+ - [A very beautiful visual background management system](https://github.com/MingZhuLiu/ZLMediaServerManagent)
+
- Media management platform
+
- [GB28181 complete solution with web management website, supporting webrtc and h265 playback](https://github.com/648540858/wvp-GB28181-pro)
- [Powerful media control and management interface platform, supporting GB28181](https://github.com/chatop2020/AKStream)
- [GB28181 server implemented in C++](https://github.com/any12345com/BXC_SipServer)
@@ -18,13 +20,15 @@ icon: circle-info
- [Hikvision ehome server implemented in Go](https://github.com/tsingeye/FreeEhome)
- Client
- - [Complete C# wrapper library for c sdk](https://github.com/malegend/ZLMediaKit.Autogen)
+
+ - [Complete C# wrapper library for c sdk](https://github.com/malegend/ZLMediaKit.Autogen)
- [Push client implemented based on C SDK](https://github.com/hctym1995/ZLM_ApiDemo)
- [Http API and Hook in C#](https://github.com/chengxiaosheng/ZLMediaKit.HttpApi)
- [RESTful client in DotNetCore](https://github.com/MingZhuLiu/ZLMediaKit.DotNetCore.Sdk)
-
+
- Player
+
- [Player supporting H265 based on wasm](https://github.com/numberwolf/h265web.js)
- - [WebSocket-fmp4 player based on MSE](https://github.com/v354412101/wsPlayer)
+ - [WebSocket-fmp4 player based on MSE](https://github.com/v354412101/wsPlayer)
- [Domestic webrtc sdk(metaRTC)](https://github.com/metartc/metaRTC)
- [GB28181 player implemented in C++](https://github.com/any12345com/BXC_gb28181Player)
diff --git a/src/more/contact.md b/src/more/contact.md
index 3258db3..620b7ee 100644
--- a/src/more/contact.md
+++ b/src/more/contact.md
@@ -8,4 +8,5 @@ icon: circle-info
- Email: <1213642868@qq.com> (For project-related or streaming media-related questions, please follow the issue process. Otherwise, we will not reply to emails.)
- QQ groups: Both QQ groups with a total of 4000 members are full. We will not create new QQ groups in the future. Users can join the [Knowledge Planet](https://github.com/ZLMediaKit/ZLMediaKit/issues/2364) to ask questions and support this project.
- Follow WeChat Official Account:
-
+
+ ![图片](https://user-images.githubusercontent.com/11495632/232451702-4c50bc72-84d8-4c94-af2b-57290088ba7a.png =200x)
diff --git a/src/more/thanks.md b/src/more/thanks.md
index 341471f..f7d644b 100644
--- a/src/more/thanks.md
+++ b/src/more/thanks.md
@@ -2,6 +2,7 @@
title: Acknowledgments
icon: circle-info
---
+
## Special Thanks
This project uses the [media-server](https://github.com/ireader/media-server) library developed by [Lao Chen](https://github.com/ireader). The reuse and de-multiplexing of ts/fmp4/mp4/ps container formats in this project depend on the media-server library. Lao Chen has provided invaluable help and support multiple times in implementing many functions of this project, and we would like to express our sincere gratitude to him!
@@ -21,7 +22,7 @@ Thanks to all those who have supported this project in various ways, including b
[DroidChow](https://github.com/DroidChow)
[阿塞](https://github.com/HuoQiShuai)
[火宣](https://github.com/ChinaCCF)
-[γ瑞γミ](https://github.com/JerryLinGd)
+[γ 瑞 γ ミ](https://github.com/JerryLinGd)
[linkingvision](https://www.linkingvision.com/)
[茄子](https://github.com/taotaobujue2008)
[好心情](mailto:409257224@qq.com)
diff --git a/src/more/use_cases.md b/src/more/use_cases.md
index 4cbc9af..773a902 100644
--- a/src/more/use_cases.md
+++ b/src/more/use_cases.md
@@ -2,6 +2,7 @@
title: Use Cases
icon: circle-info
---
-This project has received recognition from numerous companies and individual developers. According to the author's incomplete statistics,
-these companies include well-known internet giants, leading cloud service providers in China, several renowned AI unicorns,
+
+This project has received recognition from numerous companies and individual developers. According to the author's incomplete statistics,
+these companies include well-known internet giants, leading cloud service providers in China, several renowned AI unicorns,
as well as a range of small and medium-sized companies. Users can endorse this project by pasting their company name and relevant project introduction on the [issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/511) page. We appreciate your support!
diff --git a/src/reference/development_log/hls_high_performance_journey.md b/src/reference/development_log/hls_high_performance_journey.md
index 5ec4798..f5167cb 100644
--- a/src/reference/development_log/hls_high_performance_journey.md
+++ b/src/reference/development_log/hls_high_performance_journey.md
@@ -4,30 +4,32 @@ title: zlmediakit的hls高性能之旅
## 事情的起因
-北京冬奥会前夕,zlmediakit的一位用户完成了iptv系统的迁移; 由于zlmediakit对hls的支持比较完善,支持包括鉴权、统计、溯源等独家特性,所以他把之前的老系统都迁移到zlmediakit上了。
+北京冬奥会前夕,zlmediakit 的一位用户完成了 iptv 系统的迁移; 由于 zlmediakit 对 hls 的支持比较完善,支持包括鉴权、统计、溯源等独家特性,所以他把之前的老系统都迁移到 zlmediakit 上了。
-但是很不幸,在冬奥会开幕式当天,zlmediakit并没有承受起考验,当hls并发数达到3000左右时,zlmediakit线程负载接近100%,延时非常高,整个服务器基本不可用:
+但是很不幸,在冬奥会开幕式当天,zlmediakit 并没有承受起考验,当 hls 并发数达到 3000 左右时,zlmediakit 线程负载接近 100%,延时非常高,整个服务器基本不可用:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-8d6b45ad1518b2b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/320)
## 思考
-zlmediakit定位是一个通用的流媒体服务器,主要精力聚焦在rtsp/rtmp等协议,对hls的优化并不够重视,hls之前在zlmediakit里面实现方式跟http文件服务器实现方式基本一致,都是通过直接读取文件的方式提供下载。所以当hls播放数比较高时,每个用户播放都需要重新从磁盘读取一遍文件,这时文件io承压,由于磁盘慢速度的特性,不能承载太高的并发数。
-有些朋友可能会问,如果用内存虚拟磁盘能不能提高性能?答案是能,但是由于内存拷贝带宽也存在上限,所以就算hls文件都放在内存目录,每次读取文件也会存在多次memcopy,性能并不能有太大的飞跃。前面冬奥会直播事故那个案例,就是把hls文件放在内存目录,但是也就能承载2000+并发而已。
+zlmediakit 定位是一个通用的流媒体服务器,主要精力聚焦在 rtsp/rtmp 等协议,对 hls 的优化并不够重视,hls 之前在 zlmediakit 里面实现方式跟 http 文件服务器实现方式基本一致,都是通过直接读取文件的方式提供下载。所以当 hls 播放数比较高时,每个用户播放都需要重新从磁盘读取一遍文件,这时文件 io 承压,由于磁盘慢速度的特性,不能承载太高的并发数。
+有些朋友可能会问,如果用内存虚拟磁盘能不能提高性能?答案是能,但是由于内存拷贝带宽也存在上限,所以就算 hls 文件都放在内存目录,每次读取文件也会存在多次 memcopy,性能并不能有太大的飞跃。前面冬奥会直播事故那个案例,就是把 hls 文件放在内存目录,但是也就能承载 2000+并发而已。
## 歧途: sendfile
-为了解决hls并发瓶颈这个问题,我首先思考到的是`sendfile`方案。我们知道,`nginx`作为http服务器的标杆,就支持sendfile这个特性。很早之前,我就听说过`sendfile`多牛逼,它支持直接把文件发送到`socket fd`;而不用通过用户态和内核态的内存互相拷贝,可以大幅提高文件发送的性能。
-我们查看sendfile的资料,有如下介绍:
+为了解决 hls 并发瓶颈这个问题,我首先思考到的是`sendfile`方案。我们知道,`nginx`作为 http 服务器的标杆,就支持 sendfile 这个特性。很早之前,我就听说过`sendfile`多牛逼,它支持直接把文件发送到`socket fd`;而不用通过用户态和内核态的内存互相拷贝,可以大幅提高文件发送的性能。
+
+我们查看 sendfile 的资料,有如下介绍:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-74226856ef85a257.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-于是,在事故反馈当日,2022年春节期间的某天深夜,我在严寒之下光着膀子在zlmediakit中把sendfile特性实现了一遍:
+于是,在事故反馈当日,2022 年春节期间的某天深夜,我在严寒之下光着膀子在 zlmediakit 中把 sendfile 特性实现了一遍:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-512ca5a1ebd6c0dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
实现的代码如下:
-```c++
+
+```cpp
//HttpFileBody.cpp
int HttpFileBody::sendFile(int fd) {
#if defined(__linux__) || defined(__linux)
@@ -64,37 +66,37 @@ void HttpSession::sendResponse(int code,
}
```
-由于sendfile只能直接发送文件明文内容,所以并不适用于需要文件加密的https场景;这个优化,https是无法开启的;很遗憾,这次hls事故中,用户恰恰用的就是https-hls。所以本次优化并没起到实质作用(https时关闭sendfile特性是在用户反馈tls解析异常才加上的)。
+由于 sendfile 只能直接发送文件明文内容,所以并不适用于需要文件加密的 https 场景;这个优化,https 是无法开启的;很遗憾,这次 hls 事故中,用户恰恰用的就是 https-hls。所以本次优化并没起到实质作用(https 时关闭 sendfile 特性是在用户反馈 tls 解析异常才加上的)。
-## 优化之旅一:共享mmap
+## 优化之旅一:共享 mmap
-很早之前,zlmediakit已经支持mmap方式发送文件了,但是在本次hls直播事故中,并没有发挥太大的作用,原因有以下几点:
+很早之前,zlmediakit 已经支持 mmap 方式发送文件了,但是在本次 hls 直播事故中,并没有发挥太大的作用,原因有以下几点:
-- 1.每个hls播放器访问的ts文件都是独立的,每访问一次都需要建立一次mmap映射,这样导致其实每次都需要内存从文件加载一次文件到内存,并没有减少磁盘io压力。
+- 1.每个 hls 播放器访问的 ts 文件都是独立的,每访问一次都需要建立一次 mmap 映射,这样导致其实每次都需要内存从文件加载一次文件到内存,并没有减少磁盘 io 压力。
-- 2.mmap映射次数太多,导致内存不足,mmap映射失败,则会回退为fread方式。
+- 2.mmap 映射次数太多,导致内存不足,mmap 映射失败,则会回退为 fread 方式。
-- 3.由于hls m3u8索引文件是会一直覆盖重写的,而mmap在文件长度发送变化时,会触发SIGBUS的错误,之前为了修复这个bug,在访问m3u8文件时,zlmediakit会强制采用fread方案。
+- 3.由于 hls m3u8 索引文件是会一直覆盖重写的,而 mmap 在文件长度发送变化时,会触发 SIGBUS 的错误,之前为了修复这个 bug,在访问 m3u8 文件时,zlmediakit 会强制采用 fread 方案。
-于是在sendfile优化方案失败时,我想到了共享mmap方案,其优化思路如下:
+于是在 sendfile 优化方案失败时,我想到了共享 mmap 方案,其优化思路如下:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-7f703110baa254c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-共享mmap方案主要解决以下几个问题:
+共享 mmap 方案主要解决以下几个问题:
-- 防止文件多次mmap时被多次加载到内存,降低文件io压力。
+- 防止文件多次 mmap 时被多次加载到内存,降低文件 io 压力。
-- 防止mmap次数太多,导致mmap失败回退到fread方式。
+- 防止 mmap 次数太多,导致 mmap 失败回退到 fread 方式。
-- mmap映射内存在http明文传输情况下,直接写socket时不用经过内核用户态间的互相拷贝,可以降低内存带宽压力。
+- mmap 映射内存在 http 明文传输情况下,直接写 socket 时不用经过内核用户态间的互相拷贝,可以降低内存带宽压力。
于是大概在几天后,我新增了该特性:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4c1c70521321a923.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-实现代码逻辑其实比较简单,同时也比较巧妙,通过弱指针全局记录mmap实例,在无任何访问时,mmap自动回收,其代码如下:
+实现代码逻辑其实比较简单,同时也比较巧妙,通过弱指针全局记录 mmap 实例,在无任何访问时,mmap 自动回收,其代码如下:
-```c++
+```cpp
static std::shared_ptr getSharedMmap(const string &file_path, int64_t &file_size) {
{
lock_guard lck(s_mtx);
@@ -145,82 +147,85 @@ static std::shared_ptr getSharedMmap(const string &file_path, int64_t &fil
}
```
-通过本次优化,zlmediakit的hls服务有比较大的性能提升,性能上限大概提升到了6K左右(压测途中还发现拉流压测客户端由于mktime函数导致的性能瓶颈问题,在此不展开描述),但是还是离预期有些差距:
+通过本次优化,zlmediakit 的 hls 服务有比较大的性能提升,性能上限大概提升到了 6K 左右(压测途中还发现拉流压测客户端由于 mktime 函数导致的性能瓶颈问题,在此不展开描述),但是还是离预期有些差距:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9c7e706f317ea4c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
-> 小插曲: mktime函数导致拉流压测工具性能受限
+> 小插曲: mktime 函数导致拉流压测工具性能受限
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-d509266a091d97a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-## 优化之旅二:去除http cookie互斥锁
-在开启共享mmap后,发现性能上升到6K并发时,还是上不去;于是我登录服务器使用`gdb -p`调试进程,通过`info threads` 查看线程情况,发现大量线程处于阻塞状态,这也就是为什么zlmediakit占用cpu不高,但是并发却上不去的原因:
+## 优化之旅二:去除 http cookie 互斥锁
+
+在开启共享 mmap 后,发现性能上升到 6K 并发时,还是上不去;于是我登录服务器使用`gdb -p`调试进程,通过`info threads` 查看线程情况,发现大量线程处于阻塞状态,这也就是为什么 zlmediakit 占用 cpu 不高,但是并发却上不去的原因:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9b9db29311c8440a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-为什么这么多线程都处于互斥阻塞状态?zlmediakit在使用互斥锁时,还是比较注意缩小临界区的,一些复杂耗时的操作一般都会放在临界区之外;经过一番思索,我才恍然大悟,原因是:
+为什么这么多线程都处于互斥阻塞状态?zlmediakit 在使用互斥锁时,还是比较注意缩小临界区的,一些复杂耗时的操作一般都会放在临界区之外;经过一番思索,我才恍然大悟,原因是:
-> **压测客户端由于是单进程,共享同一份hls cookie,在访问zlmediakit时,这些分布在不同线程的请求,其cookie都相同,导致所有线程同时大规模操作同一个cookie,而操作cookie是要加锁的,于是这些线程疯狂的同时进行锁竞争,虽然不会死锁,但是会花费大量的时间用在锁等待上,导致整体性能降低。**
+> **压测客户端由于是单进程,共享同一份 hls cookie,在访问 zlmediakit 时,这些分布在不同线程的请求,其 cookie 都相同,导致所有线程同时大规模操作同一个 cookie,而操作 cookie 是要加锁的,于是这些线程疯狂的同时进行锁竞争,虽然不会死锁,但是会花费大量的时间用在锁等待上,导致整体性能降低。**
-虽然在真实使用场景下,用户cookie并不一致,这种几千用户同时访问同一个cookie的情况并不会存在,但是为了考虑不影响hls性能压测,也为了杜绝一切隐患,针对这个问题,我于是对http/hls的cookie机制进行了修改,在操作cookie时,不再上锁:
+虽然在真实使用场景下,用户 cookie 并不一致,这种几千用户同时访问同一个 cookie 的情况并不会存在,但是为了考虑不影响 hls 性能压测,也为了杜绝一切隐患,针对这个问题,我于是对 http/hls 的 cookie 机制进行了修改,在操作 cookie 时,不再上锁:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-ee5230a889b3891b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-348df864460eaefd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-之前对cookie上锁属于过度设计,当时目的主要是为了实现在cookie上随意挂载数据。
+之前对 cookie 上锁属于过度设计,当时目的主要是为了实现在 cookie 上随意挂载数据。
-## 优化之旅三:hls m3u8文件内存化
-经过上面两次优化,zlmediakit的hls并发能力可以达到8K了,但是当hls播放器个数达到在8K 左右时,zlmediakit的ts切片下载开始超时,可见系统还是存在性能瓶颈,联想到在优化cookie互斥锁时,有线程处于该状态:
+## 优化之旅三:hls m3u8 文件内存化
+
+经过上面两次优化,zlmediakit 的 hls 并发能力可以达到 8K 了,但是当 hls 播放器个数达到在 8K 左右时,zlmediakit 的 ts 切片下载开始超时,可见系统还是存在性能瓶颈,联想到在优化 cookie 互斥锁时,有线程处于该状态:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4c4cb2dd76e913ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
-所以我严重怀疑原因是m3u8文件不能使用mmap优化(而是采用fread方式)导致的文件io性能瓶颈问题,后面通过查看函数调用栈发现,果然是这个原因。
+所以我严重怀疑原因是 m3u8 文件不能使用 mmap 优化(而是采用 fread 方式)导致的文件 io 性能瓶颈问题,后面通过查看函数调用栈发现,果然是这个原因。
-由于m3u8是易变的,使用mmap映射时,如果文件长度发生变化,会导致触发SIGBUS的信号,查看多方资料,此问题无解。所以最后只剩下通过m3u8文件内存化来解决,于是我修好了m3u8文件的http下载方式,改成直接从内存获取:
+由于 m3u8 是易变的,使用 mmap 映射时,如果文件长度发生变化,会导致触发 SIGBUS 的信号,查看多方资料,此问题无解。所以最后只剩下通过 m3u8 文件内存化来解决,于是我修好了 m3u8 文件的 http 下载方式,改成直接从内存获取:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-175e50e0c1dbc104.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
## 结果:性能爆炸
-通过上述总共3大优化,我们在压测zlmediakit的hls性能时,随着一点一点增加并发量,发现zlmediakit总是能运行的非常健康,在并发量从10K慢慢增加到30K时,并不会影响ffplay播放的流畅性和效果,以下是压测数据:
-> 压测16K http-hls播放器时,流量大概7.5Gb/s:
-(大概需要32K端口,由于我测试机端口不足,只能最大压测到这个数据)
+通过上述总共 3 大优化,我们在压测 zlmediakit 的 hls 性能时,随着一点一点增加并发量,发现 zlmediakit 总是能运行的非常健康,在并发量从 10K 慢慢增加到 30K 时,并不会影响 ffplay 播放的流畅性和效果,以下是压测数据:
+
+> 压测 16K http-hls 播放器时,流量大概 7.5Gb/s:
+> (大概需要 32K 端口,由于我测试机端口不足,只能最大压测到这个数据)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-e4e50b03f39fb67a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-ac97bc4b78986289.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-2c64d8cd201ecd20.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-
-> 后面用户再压测了30k https-hls播放器:
+> 后面用户再压测了 30k https-hls 播放器:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4f0ca1cb2f5df91c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-1569e4c146dd47b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
-
## 后记:用户切生产环境
-在完成hls性能优化后,该用户把所有北美节点的hls流量切到了zlmediakit,
+
+在完成 hls 性能优化后,该用户把所有北美节点的 hls 流量切到了 zlmediakit,
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-10a6d17e6236fa48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-e6d38eda398a2b16.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
## 状况又起:
-今天该用户又反馈给我说zlmediakit的内存占用非常高,在30K hls并发时,内存占用30+GB:
+
+今天该用户又反馈给我说 zlmediakit 的内存占用非常高,在 30K hls 并发时,内存占用 30+GB:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-577fd6cd88b3f0f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
-但是用zlmediakit的`getThreadsLoad`接口查看,却发现负载很低:
+但是用 zlmediakit 的`getThreadsLoad`接口查看,却发现负载很低:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9b200e5fb718781b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
-同时使用zlmediakit的`getStatistic`接口查看,发现`BufferList`对象个数很高,初步怀疑是由于网络带宽不足导致发送拥塞,内存暴涨,通过询问得知,公网hls访问,确实存在ts文件下载缓慢的问题:
+同时使用 zlmediakit 的`getStatistic`接口查看,发现`BufferList`对象个数很高,初步怀疑是由于网络带宽不足导致发送拥塞,内存暴涨,通过询问得知,公网 hls 访问,确实存在 ts 文件下载缓慢的问题:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-0259d17384210378.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-同时让他通过局域网测试ts下载,却发现非常快:
+同时让他通过局域网测试 ts 下载,却发现非常快:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-368e718cc2870cc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-后来通过计算,发现确实由于网络带宽瓶颈每个用户积压一个Buffer包,而每个Buffer包用户设置的为1MB,这样算下来,30K用户,确实会积压30GB的发送缓存:
+后来通过计算,发现确实由于网络带宽瓶颈每个用户积压一个 Buffer 包,而每个 Buffer 包用户设置的为 1MB,这样算下来,30K 用户,确实会积压 30GB 的发送缓存:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-10264ff3561e6ddc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
@@ -228,11 +233,10 @@ static std::shared_ptr getSharedMmap(const string &file_path, int64_t &fil
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-d305041f6b99e04a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-
## 结论
-通过上面的经历,我们发现zlmediakit已经足以支撑30K/50Gb级别的https-hls并发能力, 理论上,http-hls相比https-hls要少1次内存拷贝,和1次加密,性能应该要好很多;那么zlmediakit的性能上限在哪里?天知道!毕竟,我已经没有这么豪华的配置供我压测了;在此,我们先立一个保守的flag吧:
-**单机 100K/100Gb级别 hls并发能力。**
+通过上面的经历,我们发现 zlmediakit 已经足以支撑 30K/50Gb 级别的 https-hls 并发能力, 理论上,http-hls 相比 https-hls 要少 1 次内存拷贝,和 1 次加密,性能应该要好很多;那么 zlmediakit 的性能上限在哪里?天知道!毕竟,我已经没有这么豪华的配置供我压测了;在此,我们先立一个保守的 flag 吧:
-那其他协议呢? 我觉得应该不输hls。
+**单机 100K/100Gb 级别 hls 并发能力。**
+那其他协议呢? 我觉得应该不输 hls。
diff --git a/src/reference/development_log/rtsp_performance_optimization.md b/src/reference/development_log/rtsp_performance_optimization.md
index dd89350..e4aace9 100644
--- a/src/reference/development_log/rtsp_performance_optimization.md
+++ b/src/reference/development_log/rtsp_performance_optimization.md
@@ -2,68 +2,71 @@
title: RTSP性能优化
order: 1
---
+
## 概述
-在最近ZLMediaKit的一次提交中,我对rtsp服务器的性能做了一次[改进](https://github.com/xiongziliang/ZLMediaKit/commit/b169f94cce1ecbab50248f25ee3b33dd40602fe1),本次改进中,核心的思想是:
-- **缓存时间戳相同的RTP包(意味着是同一帧数据),作为一个数据包进行分发**。
-理论上,这样做可以大大**减少多线程分发时线程切换次数、多余发送逻辑代码的执行以及系统调用次数**,预期在不增加播放延时的情况下能大幅提高rtsp服务器的性能.
+在最近 ZLMediaKit 的一次提交中,我对 rtsp 服务器的性能做了一次[改进](https://github.com/xiongziliang/ZLMediaKit/commit/b169f94cce1ecbab50248f25ee3b33dd40602fe1),本次改进中,核心的思想是:
+
+- **缓存时间戳相同的 RTP 包(意味着是同一帧数据),作为一个数据包进行分发**。
+
+理论上,这样做可以大大**减少多线程分发时线程切换次数、多余发送逻辑代码的执行以及系统调用次数**,预期在不增加播放延时的情况下能大幅提高 rtsp 服务器的性能.
## 测试
-为了验证本次优化的预期目标,我在linux服务器上做了一系列的测试对比,以下是测试环境:
+
+为了验证本次优化的预期目标,我在 linux 服务器上做了一系列的测试对比,以下是测试环境:
- 操作系统:ubuntu16 desktop 64bit
-- cpu: 4核心的Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
-- 编译器:gcc 5.4.0,开启Release编译(cmake -DCMAKE_BUILD_TYPE=Release)
-- malloc库:连接jemalloc
-- 网络: 127.0.0.1本地循环网络
+- cpu: 4 核心的 Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
+- 编译器:gcc 5.4.0,开启 Release 编译(cmake -DCMAKE_BUILD_TYPE=Release)
+- malloc 库:连接 jemalloc
+- 网络: 127.0.0.1 本地循环网络
- 测试客户端:[test_benchmark](https://github.com/xiongziliang/ZLMediaKit/blob/master/tests/test_benchmark.cpp)
- 测试服务器:[MediaServer](https://github.com/xiongziliang/ZLMediaKit/tree/master/server)
-- 测试码流:4K H264的RTSP流,通过MP4 Rtsp点播实现,文件200秒,190MB,码流大概8Mb/s
-- 测试方法:通过test_benchmark播放500路RTSP 4K点播,总码流大概4Gb/s,分别测试新老版本的MediaServer的进程。
-
+- 测试码流:4K H264 的 RTSP 流,通过 MP4 Rtsp 点播实现,文件 200 秒,190MB,码流大概 8Mb/s
+- 测试方法:通过 test_benchmark 播放 500 路 RTSP 4K 点播,总码流大概 4Gb/s,分别测试新老版本的 MediaServer 的进程。
## 测试数据
+
- 启动的播放器个数:
-![image](https://user-images.githubusercontent.com/11495632/78686734-f6d31180-7925-11ea-9ba3-864865a910b9.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78686734-f6d31180-7925-11ea-9ba3-864865a910b9.png)
- 实时码流:
-![image](https://user-images.githubusercontent.com/11495632/78686849-1b2eee00-7926-11ea-9434-a4f943021be5.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78686849-1b2eee00-7926-11ea-9434-a4f943021be5.png)
## 性能对比
+
### 老版本数据
-- cpu使用率(浮动比较大,最高200%+):
-![image](https://user-images.githubusercontent.com/11495632/78687097-621ce380-7926-11ea-9adb-80ccbbfca1f3.png)
-![image](https://user-images.githubusercontent.com/11495632/78687391-b031e700-7926-11ea-9b81-0339d8d9dafd.png)
+
+- cpu 使用率(浮动比较大,最高 200%+):
+ ![image](https://user-images.githubusercontent.com/11495632/78687097-621ce380-7926-11ea-9adb-80ccbbfca1f3.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78687391-b031e700-7926-11ea-9b81-0339d8d9dafd.png)
- 性能分析(perf top):
-![image](https://user-images.githubusercontent.com/11495632/78687480-c8096b00-7926-11ea-9d72-f21fffa8fd7d.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78687480-c8096b00-7926-11ea-9d72-f21fffa8fd7d.png)
-- 总结 : cpu占用主要发生在内核态的系统调用(syscall)、tcp_sendmsg、内存拷贝。
+- 总结 : cpu 占用主要发生在内核态的系统调用(syscall)、tcp_sendmsg、内存拷贝。
### 新版本数据:
-- cpu使用率(浮动比较小,50%以下):
-![image](https://user-images.githubusercontent.com/11495632/78688226-9e9d0f00-7927-11ea-8d31-49d487f339b4.png)
-![image](https://user-images.githubusercontent.com/11495632/78687893-3b12e180-7927-11ea-9e41-653b771405de.png)
-- 后面我又测试了2000个播放器,掉了一批,最后稳定在1800个左右,实时流量17.5Gb/s(单向)左右,cpu占用300%左右:
-![image](https://user-images.githubusercontent.com/11495632/78741558-39c7d000-798c-11ea-9860-6dc18db1ef0c.png)
-![image](https://user-images.githubusercontent.com/11495632/78741649-78f62100-798c-11ea-85a9-1810bf1deaf1.png)
-![image](https://user-images.githubusercontent.com/11495632/78741678-8d3a1e00-798c-11ea-9aec-dff834620781.png)
-![image](https://user-images.githubusercontent.com/11495632/78741720-ad69dd00-798c-11ea-83c6-1b0b57d79ba2.png)
+- cpu 使用率(浮动比较小,50%以下):
+ ![image](https://user-images.githubusercontent.com/11495632/78688226-9e9d0f00-7927-11ea-8d31-49d487f339b4.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78687893-3b12e180-7927-11ea-9e41-653b771405de.png)
-- 性能分析(perf top):
-![image](https://user-images.githubusercontent.com/11495632/78688104-7a413280-7927-11ea-953b-d3b9a4c5ed0c.png)
-
-- 总结 : cpu占用主要发生在内核态内存拷贝,系统调用(syscall)、tcp_sendmsg的开销很小。
+- 后面我又测试了 2000 个播放器,掉了一批,最后稳定在 1800 个左右,实时流量 17.5Gb/s(单向)左右,cpu 占用 300%左右:
+ ![image](https://user-images.githubusercontent.com/11495632/78741558-39c7d000-798c-11ea-9860-6dc18db1ef0c.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741649-78f62100-798c-11ea-85a9-1810bf1deaf1.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741678-8d3a1e00-798c-11ea-9aec-dff834620781.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741720-ad69dd00-798c-11ea-83c6-1b0b57d79ba2.png)
+- 性能分析(perf top):
+ ![image](https://user-images.githubusercontent.com/11495632/78688104-7a413280-7927-11ea-953b-d3b9a4c5ed0c.png)
+- 总结 : cpu 占用主要发生在内核态内存拷贝,系统调用(syscall)、tcp_sendmsg 的开销很小。
## 总结
-本次性能测试基本证明了预想,性能提升大概有4倍以上。
-本机器为i7-4790 4核心8线程的,所以cpu占用率最高为800%,现在ZLMediaKit在上面支撑500个4K RTSP播放器,实时流量大概4Gb/s时cpu使用率50%不到,通过简单换算,该cpu可以支撑大概8000个4K RTSP播放器,实时流量最高能达到64Gb/s,考虑到性能折损,我们保守估计可以支持6000个4K RTSP播放器,50Gb/s的流量。
-
-## 最后
-在ZLMediaKit流媒体服务器中,通过智能指针引用计数的方式实现了多线程的数据分发,不管分发多少次,数据拷贝次数都是固定的,所以ZLMediaKit可以达到如此夸张的性能参数,但是在测试中,我们也能发现,性能占用已经大部分发生在内核态了,应用层的cpu占用反而不是瓶颈了。这是因为在内核态,写socket缓存需要做内存拷贝,随着播放器个数的增加,内存拷贝会越来越多,此时性能瓶颈不再是应用层,而是由于内存带宽瓶颈导致的内核性能瓶颈。
-
+本次性能测试基本证明了预想,性能提升大概有 4 倍以上。
+本机器为 i7-4790 4 核心 8 线程的,所以 cpu 占用率最高为 800%,现在 ZLMediaKit 在上面支撑 500 个 4K RTSP 播放器,实时流量大概 4Gb/s 时 cpu 使用率 50%不到,通过简单换算,该 cpu 可以支撑大概 8000 个 4K RTSP 播放器,实时流量最高能达到 64Gb/s,考虑到性能折损,我们保守估计可以支持 6000 个 4K RTSP 播放器,50Gb/s 的流量。
+## 最后
+在 ZLMediaKit 流媒体服务器中,通过智能指针引用计数的方式实现了多线程的数据分发,不管分发多少次,数据拷贝次数都是固定的,所以 ZLMediaKit 可以达到如此夸张的性能参数,但是在测试中,我们也能发现,性能占用已经大部分发生在内核态了,应用层的 cpu 占用反而不是瓶颈了。这是因为在内核态,写 socket 缓存需要做内存拷贝,随着播放器个数的增加,内存拷贝会越来越多,此时性能瓶颈不再是应用层,而是由于内存带宽瓶颈导致的内核性能瓶颈。
diff --git a/src/reference/documents/exclusive_features.md b/src/reference/documents/exclusive_features.md
index 9e3b4fa..897d653 100644
--- a/src/reference/documents/exclusive_features.md
+++ b/src/reference/documents/exclusive_features.md
@@ -1,6 +1,7 @@
---
title: Exclusive Features of ZLMediakit
---
+
## 1. Play before Publishing
- Pain point: Unable to play before successful publishing.
@@ -21,7 +22,6 @@ title: Exclusive Features of ZLMediakit
> Note: This feature also applies to pulling streams, allowing on-demand publishing and pulling of streams.
-
## 2. No Viewer Event
- Pain point: Wasting bandwidth when streaming has no viewers.
@@ -60,7 +60,6 @@ title: Exclusive Features of ZLMediakit
> Note: Introduction to hooks can be found [here](../../guide/media_server/web_hook_api.md#14on_stream_not_found).
-
## 4. Reconnect after disconnection and continue pushing stream
- Pain point: When the pushing stream is disconnected and the pushing stream device reconnects, all the players are disconnected as well.
@@ -81,13 +80,12 @@ title: Exclusive Features of ZLMediakit
continue_push_ms=15000
```
-
- Implementation code snippet:
- ```c++
+ ```cpp
void RtmpSession::onError(const SockException& err) {
// Omit irrelevant code
-
+
GET_CONFIG(uint32_t, continue_push_ms, General::kContinuePushMS);
if (_push_src && continue_push_ms) {
// Release ownership of the pushing stream object
@@ -97,11 +95,11 @@ title: Exclusive Features of ZLMediakit
getPoller()->doDelayTask(continue_push_ms, [push_src]() { return 0; });
}
}
-
+
void RtmpSession::onCmd_publish(AMFDecoder &dec) {
// Omit a large amount of irrelevant code
auto src = MediaSource::find(RTMP_SCHEMA, _media_info._vhost, _media_info._app, _media_info._streamid);
-
+
while (src) {
// Attempt to continue pushing stream after disconnection
auto rtmp_src = dynamic_pointer_cast(src);
@@ -126,7 +124,6 @@ title: Exclusive Features of ZLMediakit
> Note: Continuous disconnection and reconnection feature supports RTSP/RTMP/WebRTC pushing stream.
-
## 5. Cluster Deployment
- Pain point: Limited traceability methods, edge servers cannot use HLS.
@@ -152,7 +149,7 @@ title: Exclusive Features of ZLMediakit
```
ZLMediakit supports multiple ways of pulling streams, including rtsp/rtmp/hls/http-ts/http-flv. The methods are diverse and rich, and the origin servers are not divided into primary and backup. Load balancing of the origin servers is achieved using the round-robin method. It should be noted that since ZLMediakit has long supported on-demand streaming for HLS, its edge stations also support the HLS protocol (in fact, they support any protocol supported by ZLMediakit), which is not available in SRS.
-
+
Furthermore, it should be noted that ZLMediakit supports both RTSP and WebRTC, both of which are based on RTP. Internally in ZLMediakit, they can be interconnected without the need for protocol conversion and complex multiplexing/demultiplexing logic. This makes it possible to use ZLMediakit for large-scale, low-latency WebRTC live streaming. Compared to traditional CDN based on RTMP, RTSP is more suitable as the underlying transport protocol for WebRTC. Developers do not need to deal with cumbersome multiplexing/demultiplexing logic and can smoothly achieve the interconversion between RTSP and WebRTC.
## 6. WebRTC Single Port, Multi-threading, and Connection Migration Support
@@ -184,5 +181,3 @@ ZLMediakit achieves long connection for HLS playback through cookie tracking tec
- On-demandI'm sorry, but I couldn't find any information about a specific ZLMediakit feature called "pull stream URL of the origin server." ZLMediakit is an open-source streaming media server that provides various features for streaming protocols like RTSP, RTMP, HLS, and WebRTC.
If you have any specific questions about ZLMediakit or need information on a different feature, please let me know, and I'll do my best to assist you.
-
-
diff --git a/src/reference/documents/high_concurrency_implementation_principle.md b/src/reference/documents/high_concurrency_implementation_principle.md
index 5489b5b..8a2a75c 100644
--- a/src/reference/documents/high_concurrency_implementation_principle.md
+++ b/src/reference/documents/high_concurrency_implementation_principle.md
@@ -1,47 +1,48 @@
---
title: ZLMediaKit高并发实现原理
---
-# 项目介绍
-[ZLMediaKit](https://github.com/xiongziliang/ZLMediaKit)是一套高性能的流媒体服务框架,目前支持rtmp/rtsp/hls/http-flv流媒体协议。该项目已支持linux、macos、windows、ios、android平台,支持的编码格式包括H264、AAC、H265(仅rtsp支持H265);采用的模型是多线程IO多路复用非阻塞式编程(linux下采用epoll、其他平台采用select)。
-
-该框架基于C++11开发,避免使用裸指针,减少内存拷贝,代码精简可靠,并发性能优异,在linux平台下,单一进程即可充分利用多核CPU的优势;最大限度的榨干CPU、网卡性能;轻松达到万兆网卡性能极限。同时也能在高性能的同时,做到极低延时,画面秒开。
-
-目前ZLMediaKit经过多次版本迭代,编程模型多次升级优化;已经趋于成熟稳定,也在各种生产环境得到了验证,本文主要讨论ZLMediaKit高性能实现原理以及项目特点。
+## 项目介绍
-# 网络模型对比
+[ZLMediaKit](https://github.com/xiongziliang/ZLMediaKit)是一套高性能的流媒体服务框架,目前支持 rtmp/rtsp/hls/http-flv 流媒体协议。该项目已支持 linux、macos、windows、ios、android 平台,支持的编码格式包括 H264、AAC、H265(仅 rtsp 支持 H265);采用的模型是多线程 IO 多路复用非阻塞式编程(linux 下采用 epoll、其他平台采用 select)。
-不同于SRS的单线程多协程、node.js/redis的单线程、NGINX的多进程模型;ZLMediaKit采用的是单进程多线程模型。那么为什么ZLMediaKit要采用这样的编程模型呢?
+该框架基于 C++11 开发,避免使用裸指针,减少内存拷贝,代码精简可靠,并发性能优异,在 linux 平台下,单一进程即可充分利用多核 CPU 的优势;最大限度的榨干 CPU、网卡性能;轻松达到万兆网卡性能极限。同时也能在高性能的同时,做到极低延时,画面秒开。
-作为一个多年的C++服务器后台开发工程师,多年的工作经验告诉我,作为一个服务器程序,对于稳定性要求极高;一个服务器可以性能差点,但是绝不能轻易core dump;服务中断、重启、异常,对于一个线上已运营项目来说结果是灾难性的。那么我们该怎么确保服务器的稳定?目前有以下手段:
+目前 ZLMediaKit 经过多次版本迭代,编程模型多次升级优化;已经趋于成熟稳定,也在各种生产环境得到了验证,本文主要讨论 ZLMediaKit 高性能实现原理以及项目特点。
+
+## 网络模型对比
+
+不同于 SRS 的单线程多协程、node.js/redis 的单线程、NGINX 的多进程模型;ZLMediaKit 采用的是单进程多线程模型。那么为什么 ZLMediaKit 要采用这样的编程模型呢?
+
+作为一个多年的 C++服务器后台开发工程师,多年的工作经验告诉我,作为一个服务器程序,对于稳定性要求极高;一个服务器可以性能差点,但是绝不能轻易 core dump;服务中断、重启、异常,对于一个线上已运营项目来说结果是灾难性的。那么我们该怎么确保服务器的稳定?目前有以下手段:
- 单线程模型
- 单线程+协程
- 单线程+多进程
- 多线程+锁
-- 弃用C/C++
+- 弃用 C/C++
-采用单线程模型的优点是,服务器简单可靠,不用考虑资源竞争互斥的问题,这样可以比较容易做到高稳定性;采用此模型的典型代表项目有 redis、node.js。但是由于是单线程模型,所以弊端也比较明显;那就是在多核cpu上不能充分利用多核CPU的算力,性能瓶颈主要在于CPU(大家应该有过在redis中执行keys *慢慢等待的经历)。
+采用单线程模型的优点是,服务器简单可靠,不用考虑资源竞争互斥的问题,这样可以比较容易做到高稳定性;采用此模型的典型代表项目有 redis、node.js。但是由于是单线程模型,所以弊端也比较明显;那就是在多核 cpu 上不能充分利用多核 CPU 的算力,性能瓶颈主要在于 CPU(大家应该有过在 redis 中执行 keys \*慢慢等待的经历)。
![img](https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3069000473,466332746&fm=26&gp=0.jpg)
-单线程+协程的方案本质上与纯单线程模型无区别,它们的区别主要编程风格上。纯单线程模型使用的是非阻塞式处处回调方式实现高并发,这种模型会有所谓的回调地狱的问题,编程起来会比较麻烦。而单线程+协程的方案是简化编程方式,采用自然的阻塞式编程风格,在协程库内部管理任务调度,本质也是非阻塞的。但是协程库涉及的比较底层,跟系统息息相关,所以跨平台不是很好做,而且设计实现一个协程库门槛较高。SRS采用就是这编程模型,由于协程库的限制,SRS不能在windows上运行。
+单线程+协程的方案本质上与纯单线程模型无区别,它们的区别主要编程风格上。纯单线程模型使用的是非阻塞式处处回调方式实现高并发,这种模型会有所谓的回调地狱的问题,编程起来会比较麻烦。而单线程+协程的方案是简化编程方式,采用自然的阻塞式编程风格,在协程库内部管理任务调度,本质也是非阻塞的。但是协程库涉及的比较底层,跟系统息息相关,所以跨平台不是很好做,而且设计实现一个协程库门槛较高。SRS 采用就是这编程模型,由于协程库的限制,SRS 不能在 windows 上运行。
-为了解决上述单线程模型的问题,很多服务器采用单线程多进程的编程模型;在这种模型下,既有单线程模型的简单可靠的特性,又能充分发挥多核CPU的性能,而且某个进程挂了也不会影响其他进程,像NGINX就是这种编程模型;但是这种模型也有其局限性。在这种模型下,会话间是相互隔离的,两个会话可能运行在不同的进程上;这样就导致了会话间通信的困难。比如说A用户连接在服务器A进程上,B用户连接在服务器B进程上;如果两者之间要完成某种数据交互,那么会异常困难,这样必须通过进程间通信来完成。而进程间通信代价和开销比较大,编程起来也比较困难。但是如果会话间无需数据交互(例如http服务器),那么这种模型是特别适合的,所以NGINX作为http服务器也是非常成功的,但是如果是譬如即时聊天的那种需要会话间通信的服务,那么这种开发模型不是很适合。不过现在越来越多的服务都需要支持分布式集群部署,所以单线程多进程方案的缺陷越来越不明显。
+为了解决上述单线程模型的问题,很多服务器采用单线程多进程的编程模型;在这种模型下,既有单线程模型的简单可靠的特性,又能充分发挥多核 CPU 的性能,而且某个进程挂了也不会影响其他进程,像 NGINX 就是这种编程模型;但是这种模型也有其局限性。在这种模型下,会话间是相互隔离的,两个会话可能运行在不同的进程上;这样就导致了会话间通信的困难。比如说 A 用户连接在服务器 A 进程上,B 用户连接在服务器 B 进程上;如果两者之间要完成某种数据交互,那么会异常困难,这样必须通过进程间通信来完成。而进程间通信代价和开销比较大,编程起来也比较困难。但是如果会话间无需数据交互(例如 http 服务器),那么这种模型是特别适合的,所以 NGINX 作为 http 服务器也是非常成功的,但是如果是譬如即时聊天的那种需要会话间通信的服务,那么这种开发模型不是很适合。不过现在越来越多的服务都需要支持分布式集群部署,所以单线程多进程方案的缺陷越来越不明显。
-由于C/C++是种强类型静态语言,异常处理简单粗暴,动不动就core dump。C/C++的设计理念就是发现错误及早暴露,在某种意义上来说,崩溃也是种好事,因为这样会引起你的重视,让你能及早发现定位并解决问题,而不是把问题拖延到无法解决的时候再暴露给你。但是这么做对一般人来说,C/C++就不是很友好了,人类并不像机器那样严谨,有点疏忽在所难免,况且有些小问题也无伤大雅,并不需要毁灭式的core dump来应对。而且C/C++的学习曲线异常艰难困苦,很多人好几年也不得要领,所以很多人表示纷纷弃坑,转投 go / erlang / node.js之类。
+由于 C/C++是种强类型静态语言,异常处理简单粗暴,动不动就 core dump。C/C++的设计理念就是发现错误及早暴露,在某种意义上来说,崩溃也是种好事,因为这样会引起你的重视,让你能及早发现定位并解决问题,而不是把问题拖延到无法解决的时候再暴露给你。但是这么做对一般人来说,C/C++就不是很友好了,人类并不像机器那样严谨,有点疏忽在所难免,况且有些小问题也无伤大雅,并不需要毁灭式的 core dump 来应对。而且 C/C++的学习曲线异常艰难困苦,很多人好几年也不得要领,所以很多人表示纷纷弃坑,转投 go / erlang / node.js 之类。
-但是C/C++由于其性能优越性,以及历史原因,在某些场景下是不二选择,而且C/C++才是真正的跨平台语言;况且随着智能指针的推出,内存管理不再是难题;而lambda语法的支持,让程序上下文绑定不再困难。随着C++新特性的支持,编译器静态反射机制的完善,现代C++编程愈发简便快捷。ZLMediaKit采用的就是C++11新标准以及相关理念完成的高性能流媒体服务框架。
+但是 C/C++由于其性能优越性,以及历史原因,在某些场景下是不二选择,而且 C/C++才是真正的跨平台语言;况且随着智能指针的推出,内存管理不再是难题;而 lambda 语法的支持,让程序上下文绑定不再困难。随着 C++新特性的支持,编译器静态反射机制的完善,现代 C++编程愈发简便快捷。ZLMediaKit 采用的就是 C++11 新标准以及相关理念完成的高性能流媒体服务框架。
-与上面其它编程模型不同,ZLMediaKit采用的是多线程开发模型;与传统的多线程模型不同;ZLMediaKit采用了C++11的智能指针来做内存管理,在线程切换时可以完美的管理内存在多线程下共享以及其生命周期。同时互斥锁的粒度消减至极致,几乎可以忽略不计。所以采用多线程模型的ZLMediaKit性能损耗极低,每条线程的性能几乎可以媲美单线程模型,同时也可以充分榨干CPU的每一核心性能。
+与上面其它编程模型不同,ZLMediaKit 采用的是多线程开发模型;与传统的多线程模型不同;ZLMediaKit 采用了 C++11 的智能指针来做内存管理,在线程切换时可以完美的管理内存在多线程下共享以及其生命周期。同时互斥锁的粒度消减至极致,几乎可以忽略不计。所以采用多线程模型的 ZLMediaKit 性能损耗极低,每条线程的性能几乎可以媲美单线程模型,同时也可以充分榨干 CPU 的每一核心性能。
-# 网络模型详述
+## 网络模型详述
-ZLMediaKit在启动时会根据cpu核心数自动创建若干个epoll实例(非linux平台为select);这些epoll实例都会有一个线程来运行`epoll_wait`函数来等待事件的触发。
+ZLMediaKit 在启动时会根据 cpu 核心数自动创建若干个 epoll 实例(非 linux 平台为 select);这些 epoll 实例都会有一个线程来运行`epoll_wait`函数来等待事件的触发。
-以ZLMediaKit的RTMP服务为例,在创建一个`TcpServer`时,ZLMediaKit会把这个Tcp服务的监听套接字加入到每一个epoll实例,这样如果收到新的RTMP播放请求,那么多个epoll实例会在内核的调度下,自动选择负载较轻的线程触发accept事件,以下是代码片段:
+以 ZLMediaKit 的 RTMP 服务为例,在创建一个`TcpServer`时,ZLMediaKit 会把这个 Tcp 服务的监听套接字加入到每一个 epoll 实例,这样如果收到新的 RTMP 播放请求,那么多个 epoll 实例会在内核的调度下,自动选择负载较轻的线程触发 accept 事件,以下是代码片段:
-```c++
+```cpp
template
void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog = 1024) {
start_l(port,host,backlog);
@@ -53,7 +54,7 @@ void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog
}
auto &serverRef = _clonedServer[poller.get()];
if(!serverRef){
- //绑定epoll实例
+ //绑定epoll实例
serverRef = std::make_shared(poller);
}
serverRef->cloneFrom(*this);
@@ -62,32 +63,30 @@ void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog
void cloneFrom(const TcpServer &that){
- if(!that._socket){
- throw std::invalid_argument("TcpServer::cloneFrom other with null socket!");
- }
- _sessionMaker = that._sessionMaker;
- //克隆一个相同fd的Socket对象
- _socket->cloneFromListenSocket(*(that._socket));
- _timer = std::make_shared(2, [this]()->bool {
- this->onManagerSession();
- return true;
- },_poller);
- this->mINI::operator=(that);
+ if(!that._socket){
+ throw std::invalid_argument("TcpServer::cloneFrom other with null socket!");
+ }
+ _sessionMaker = that._sessionMaker;
+ //克隆一个相同fd的Socket对象
+ _socket->cloneFromListenSocket(*(that._socket));
+ _timer = std::make_shared(2, [this]()->bool {
+ this->onManagerSession();
+ return true;
+ },_poller);
+ this->mINI::operator=(that);
_cloned = true;
- }
+ }
```
+服务器在收到 accept 事件后,会创建一个`TcpSession`对象并绑定到该 epoll 实例(同时把与之对应的`peer fd`加入到相关 epoll 监听)。每一个 Tcp 连接都会对应一个`TcpSession`对象,在之后客户端与服务器的数据交互中,该`TcpSession`对象处理一切与之相关的业务数据,并且该对象之后生命周期内的一切事件都会由该 epoll 线程触发,这样服务器的每个 epoll 线程都能均匀的分派到合理的客户端数量。以下是服务器 accept 事件处理逻辑代码片段:
-
-服务器在收到accept事件后,会创建一个`TcpSession`对象并绑定到该epoll实例(同时把与之对应的`peer fd`加入到相关epoll监听)。每一个Tcp连接都会对应一个`TcpSession`对象,在之后客户端与服务器的数据交互中,该`TcpSession`对象处理一切与之相关的业务数据,并且该对象之后生命周期内的一切事件都会由该epoll线程触发,这样服务器的每个epoll线程都能均匀的分派到合理的客户端数量。以下是服务器accept事件处理逻辑代码片段:
-
-```c++
+```cpp
// 接收到客户端连接请求
virtual void onAcceptConnection(const Socket::Ptr & sock) {
- weak_ptr weakSelf = shared_from_this();
+ weak_ptr weakSelf = shared_from_this();
//创建一个TcpSession;这里实现创建不同的服务会话实例
- auto sessionHelper = _sessionMaker(weakSelf,sock);
- auto &session = sessionHelper->session();
+ auto sessionHelper = _sessionMaker(weakSelf,sock);
+ auto &session = sessionHelper->session();
//把本服务器的配置传递给TcpSession
session->attachServer(*this);
@@ -105,25 +104,25 @@ void cloneFrom(const TcpServer &that){
assert(success == true);
weak_ptr weakSession(session);
- //会话接收数据事件
- sock->setOnRead([weakSession](const Buffer::Ptr &buf, struct sockaddr *addr){
- //获取会话强引用
- auto strongSession=weakSession.lock();
- if(!strongSession) {
- //会话对象已释放
- return;
- }
+ //会话接收数据事件
+ sock->setOnRead([weakSession](const Buffer::Ptr &buf, struct sockaddr *addr){
+ //获取会话强引用
+ auto strongSession=weakSession.lock();
+ if(!strongSession) {
+ //会话对象已释放
+ return;
+ }
//TcpSession处理业务数据
- strongSession->onRecv(buf);
- });
+ strongSession->onRecv(buf);
+ });
- //会话接收到错误事件
- sock->setOnErr([weakSelf,weakSession,sessionId](const SockException &err){
- //在本函数作用域结束时移除会话对象
+ //会话接收到错误事件
+ sock->setOnErr([weakSelf,weakSession,sessionId](const SockException &err){
+ //在本函数作用域结束时移除会话对象
//目的是确保移除会话前执行其onError函数
//同时避免其onError函数抛异常时没有移除会话对象
- onceToken token(nullptr,[&](){
+ onceToken token(nullptr,[&](){
//移除掉会话
SessionMap::Instance().remove(sessionId);
auto strongSelf = weakSelf.lock();
@@ -138,59 +137,57 @@ void cloneFrom(const TcpServer &that){
}
strongSelf->_sessionMap.erase(sessionId);
});
- });
- //获取会话强应用
- auto strongSession=weakSession.lock();
+ });
+ //获取会话强应用
+ auto strongSession=weakSession.lock();
if(strongSession) {
//触发onError事件回调
- strongSession->onError(err);
- }
- });
- }
+ strongSession->onError(err);
+ }
+ });
+ }
```
+通过上诉描述,我们应该大概了解了 ZLMediaKit 的网络模型,通过这样的模型基本上能榨干 CPU 的算力,不过 CPU 算力如果使用不当 ,也可能白白浪费,使之做一些无用的事务,那么在 ZLMediaKit 中还有那些技术手段来提高性能呢?我们在下节展开论述。
+## 关闭互斥锁
-通过上诉描述,我们应该大概了解了ZLMediaKit的网络模型,通过这样的模型基本上能榨干CPU的算力,不过CPU算力如果使用不当 ,也可能白白浪费,使之做一些无用的事务,那么在ZLMediaKit中还有那些技术手段来提高性能呢?我们在下节展开论述。
-
-# 关闭互斥锁
-
-上一节论述中,我们知道`TcpSession`是ZLMediaKit中的关键元素,服务器大部分计算都在TcpSession内完成。一个`TcpSession`由一个epoll实例掌管其生命周期,其他线程不得直接操作该`TcpSession`对象(必须通过线程切换到对应的epoll线程来完成操作);所以从某种意义上来说`TcpSeesion`是单线程模型的;所以ZLMediaKit对于`TcpSession`所对应的网络io操作是无互斥锁保护的,ZLMediaKit作为服务器模式运行,基本上是无锁的;这种情况下,锁对性能的影响几乎可以忽略不计。以下是ZLMediaKit关闭互斥锁的代码片段:
+上一节论述中,我们知道`TcpSession`是 ZLMediaKit 中的关键元素,服务器大部分计算都在 TcpSession 内完成。一个`TcpSession`由一个 epoll 实例掌管其生命周期,其他线程不得直接操作该`TcpSession`对象(必须通过线程切换到对应的 epoll 线程来完成操作);所以从某种意义上来说`TcpSeesion`是单线程模型的;所以 ZLMediaKit 对于`TcpSession`所对应的网络 io 操作是无互斥锁保护的,ZLMediaKit 作为服务器模式运行,基本上是无锁的;这种情况下,锁对性能的影响几乎可以忽略不计。以下是 ZLMediaKit 关闭互斥锁的代码片段:
-```c++
+```cpp
virtual Socket::Ptr onBeforeAcceptConnection(const EventPoller::Ptr &poller){
- /**
- * 服务器模型socket是线程安全的,所以为了提高性能,关闭互斥锁
- * Socket构造函数第二个参数即为是否关闭互斥锁
- */
- return std::make_shared(poller,false);
- }
+ /**
+ * 服务器模型socket是线程安全的,所以为了提高性能,关闭互斥锁
+ * Socket构造函数第二个参数即为是否关闭互斥锁
+ */
+ return std::make_shared(poller,false);
+ }
//Socket对象的构造函数,第二个参数即为是否关闭互斥锁
Socket::Socket(const EventPoller::Ptr &poller,bool enableMutex) :
- _mtx_sockFd(enableMutex),
- _mtx_bufferWaiting(enableMutex),
- _mtx_bufferSending(enableMutex) {
- _poller = poller;
- if(!_poller){
- _poller = EventPollerPool::Instance().getPoller();
- }
+ _mtx_sockFd(enableMutex),
+ _mtx_bufferWaiting(enableMutex),
+ _mtx_bufferSending(enableMutex) {
+ _poller = poller;
+ if(!_poller){
+ _poller = EventPollerPool::Instance().getPoller();
+ }
_canSendSock = true;
- _readCB = [](const Buffer::Ptr &buf,struct sockaddr *) {
- WarnL << "Socket not set readCB";
- };
- _errCB = [](const SockException &err) {
- WarnL << "Socket not set errCB:" << err.what();
- };
- _acceptCB = [](Socket::Ptr &sock) {
- WarnL << "Socket not set acceptCB";
- };
- _flushCB = []() {return true;};
-
- _beforeAcceptCB = [](const EventPoller::Ptr &poller){
- return nullptr;
- };
+ _readCB = [](const Buffer::Ptr &buf,struct sockaddr *) {
+ WarnL << "Socket not set readCB";
+ };
+ _errCB = [](const SockException &err) {
+ WarnL << "Socket not set errCB:" << err.what();
+ };
+ _acceptCB = [](Socket::Ptr &sock) {
+ WarnL << "Socket not set acceptCB";
+ };
+ _flushCB = []() {return true;};
+
+ _beforeAcceptCB = [](const EventPoller::Ptr &poller){
+ return nullptr;
+ };
}
//MutexWrapper对象定义,可以选择是否关闭互斥锁
@@ -219,77 +216,75 @@ private:
```
-
-
-# 规避内存拷贝
+## 规避内存拷贝
传统的多线程模型下,做数据转发会存在线程切换的问题,为了确保线程安全,一般使用内存拷贝来规避该问题;而且对数据进行分包处理也很难做到不使用内存拷贝。但是流媒体这种业务逻辑,可能观看同一个直播的用户是海量的,如果每分发一次就做内存拷贝,那么开销是十分可观的,这将严重拖累服务器性能。
-ZLMediaKit在做媒体数据转发时,是不会做内存拷贝的,常规的C++多线程编程很难做到这一点,但是我们在C++11的加持下,利用引用计数,巧妙的解决了多线程内存生命周期管理的问题,以下是RTMP服务器做媒体数据分发规避内存拷贝的代码片段:
+ZLMediaKit 在做媒体数据转发时,是不会做内存拷贝的,常规的 C++多线程编程很难做到这一点,但是我们在 C++11 的加持下,利用引用计数,巧妙的解决了多线程内存生命周期管理的问题,以下是 RTMP 服务器做媒体数据分发规避内存拷贝的代码片段:
-```c++
+```cpp
void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
const Buffer::Ptr &buf, uint32_t ui32TimeStamp, int iChunkId){
- if (iChunkId < 2 || iChunkId > 63) {
- auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl;
- throw std::runtime_error(strErr);
+ if (iChunkId < 2 || iChunkId > 63) {
+ auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl;
+ throw std::runtime_error(strErr);
+ }
+ //是否有扩展时间戳
+ bool bExtStamp = ui32TimeStamp >= 0xFFFFFF;
+
+ // rtmp头
+ BufferRaw::Ptr bufferHeader = obtainBuffer();
+ bufferHeader->setCapacity(sizeof(RtmpHeader));
+ bufferHeader->setSize(sizeof(RtmpHeader));
+ //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
+ RtmpHeader *header = (RtmpHeader*) bufferHeader->data();
+ header->flags = (iChunkId & 0x3f) | (0 << 6);
+ header->typeId = ui8Type;
+ set_be24(header->timeStamp, bExtStamp ? 0xFFFFFF : ui32TimeStamp);
+ set_be24(header->bodySize, buf->size());
+ set_le32(header->streamId, ui32StreamId);
+ //发送rtmp头
+ onSendRawData(bufferHeader);
+
+ //扩展时间戳字段
+ BufferRaw::Ptr bufferExtStamp;
+ if (bExtStamp) {
+ //生成扩展时间戳
+ bufferExtStamp = obtainBuffer();
+ bufferExtStamp->setCapacity(4);
+ bufferExtStamp->setSize(4);
+ set_be32(bufferExtStamp->data(), ui32TimeStamp);
+ }
+
+ //生成一个字节的flag,标明是什么chunkId
+ BufferRaw::Ptr bufferFlags = obtainBuffer();
+ bufferFlags->setCapacity(1);
+ bufferFlags->setSize(1);
+ bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6);
+
+ size_t offset = 0;
+ uint32_t totalSize = sizeof(RtmpHeader);
+ while (offset < buf->size()) {
+ if (offset) {
+ //发送trunkId
+ onSendRawData(bufferFlags);
+ totalSize += 1;
}
- //是否有扩展时间戳
- bool bExtStamp = ui32TimeStamp >= 0xFFFFFF;
-
- //rtmp头
- BufferRaw::Ptr bufferHeader = obtainBuffer();
- bufferHeader->setCapacity(sizeof(RtmpHeader));
- bufferHeader->setSize(sizeof(RtmpHeader));
- //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
- RtmpHeader *header = (RtmpHeader*) bufferHeader->data();
- header->flags = (iChunkId & 0x3f) | (0 << 6);
- header->typeId = ui8Type;
- set_be24(header->timeStamp, bExtStamp ? 0xFFFFFF : ui32TimeStamp);
- set_be24(header->bodySize, buf->size());
- set_le32(header->streamId, ui32StreamId);
- //发送rtmp头
- onSendRawData(bufferHeader);
-
- //扩展时间戳字段
- BufferRaw::Ptr bufferExtStamp;
if (bExtStamp) {
- //生成扩展时间戳
- bufferExtStamp = obtainBuffer();
- bufferExtStamp->setCapacity(4);
- bufferExtStamp->setSize(4);
- set_be32(bufferExtStamp->data(), ui32TimeStamp);
- }
-
- //生成一个字节的flag,标明是什么chunkId
- BufferRaw::Ptr bufferFlags = obtainBuffer();
- bufferFlags->setCapacity(1);
- bufferFlags->setSize(1);
- bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6);
-
- size_t offset = 0;
- uint32_t totalSize = sizeof(RtmpHeader);
- while (offset < buf->size()) {
- if (offset) {
- //发送trunkId
- onSendRawData(bufferFlags);
- totalSize += 1;
- }
- if (bExtStamp) {
- //扩展时间戳
- onSendRawData(bufferExtStamp);
- totalSize += 4;
- }
- size_t chunk = min(_iChunkLenOut, buf->size() - offset);
- //分发流媒体数据包,此处规避了内存拷贝
- onSendRawData(std::make_shared(buf,offset,chunk));
- totalSize += chunk;
- offset += chunk;
+ //扩展时间戳
+ onSendRawData(bufferExtStamp);
+ totalSize += 4;
+ }
+ size_t chunk = min(_iChunkLenOut, buf->size() - offset);
+ //分发流媒体数据包,此处规避了内存拷贝
+ onSendRawData(std::make_shared(buf,offset,chunk));
+ totalSize += chunk;
+ offset += chunk;
}
_ui32ByteSent += totalSize;
if (_ui32WinSize > 0 && _ui32ByteSent - _ui32LastSent >= _ui32WinSize) {
- _ui32LastSent = _ui32ByteSent;
- sendAcknowledgement(_ui32ByteSent);
+ _ui32LastSent = _ui32ByteSent;
+ sendAcknowledgement(_ui32ByteSent);
}
}
@@ -318,20 +313,20 @@ private:
```
-我们在发送RTP包时也是采用同样的原理来避免内存拷贝。
+我们在发送 RTP 包时也是采用同样的原理来避免内存拷贝。
-# 使用对象循环池
+## 使用对象循环池
-内存开辟销毁是全局互斥的,过多的new/delete 不仅降低程序性能,还会导致内存碎片。ZLMediaKit尽量使用循环池来避免这些问题,以下代码时RTP包循环池使用代码片段:
+内存开辟销毁是全局互斥的,过多的 new/delete 不仅降低程序性能,还会导致内存碎片。ZLMediaKit 尽量使用循环池来避免这些问题,以下代码时 RTP 包循环池使用代码片段:
-```c++
+```cpp
RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, unsigned int len, bool mark, uint32_t uiStamp) {
uint16_t ui16RtpLen = len + 12;
uint32_t ts = htonl((_ui32SampleRate / 1000) * uiStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
- //采用循环池来获取rtp对象
+ //采用循环池来获取rtp对象
auto rtppkt = ResourcePoolHelper::obtainObj();
unsigned char *pucRtp = rtppkt->payload;
pucRtp[0] = '$';
@@ -362,21 +357,19 @@ RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, unsigned int l
}
```
+## 设置 Socket 相关标志
+开启 TCP_NODELAY 后可以提高服务器响应速度,对于一些对延时要求比较敏感的服务(比如 ssh 服务),开启 TCP_NODELAY 标记比较重要。但是对于流媒体服务,由于数据是源源不断并且量也比较大,所以关闭 TCP_NODELAY 可以减少 ACK 包数量,充分利用带宽资源。
-# 设置Socket相关标志
-
-开启TCP_NODELAY后可以提高服务器响应速度,对于一些对延时要求比较敏感的服务(比如ssh服务),开启TCP_NODELAY标记比较重要。但是对于流媒体服务,由于数据是源源不断并且量也比较大,所以关闭TCP_NODELAY可以减少ACK包数量,充分利用带宽资源。
+MSG_MORE 是另外一个提高网络吞吐量的标记;这个标记的作用是在发送数据时,服务器会缓存一定的数据然后再打包一次性发送出去;而像 RTSP 这种业务场景,MSG_MORE 标记就显得格外合适;因为 RTP 包一般都很小(小于 MTU),通过 MSG_MORE 标记可以极大减少数据包个数。
-MSG_MORE是另外一个提高网络吞吐量的标记;这个标记的作用是在发送数据时,服务器会缓存一定的数据然后再打包一次性发送出去;而像RTSP这种业务场景,MSG_MORE标记就显得格外合适;因为RTP包一般都很小(小于MTU),通过MSG_MORE标记可以极大减少数据包个数。
+ZLMediaKit 在处理播放器时,握手期间是开启 TCP_NODELAY 并且关闭 MSG_MORE 的,这样做的目的是提高握手期间数据交互的延时,减少链接建立耗时,提高视频打开速度。在握手成功后,ZLMediaKit 会关闭 TCP_NODELAY 并打开 MSG_MORE;这样又能减少数据报文个数,提高网络利用率。
-ZLMediaKit在处理播放器时,握手期间是开启TCP_NODELAY并且关闭MSG_MORE的,这样做的目的是提高握手期间数据交互的延时,减少链接建立耗时,提高视频打开速度。在握手成功后,ZLMediaKit会关闭TCP_NODELAY并打开MSG_MORE;这样又能减少数据报文个数,提高网络利用率。
+## 批量数据发送
-# 批量数据发送
+网络编程中,大家应该都用过 send/sendto/write 函数,但是 writev/sendmsg 函数应该用的不多。ZLMediaKit 采用 sendmsg 函数来做批量数据发送,这样在网络不是很好或者服务器负载比较高时,可以明显减少系统调用(系统调用开销比较大)次数,提高程序性能。以下是代码片段:
-网络编程中,大家应该都用过send/sendto/write函数,但是writev/sendmsg函数应该用的不多。ZLMediaKit采用sendmsg函数来做批量数据发送,这样在网络不是很好或者服务器负载比较高时,可以明显减少系统调用(系统调用开销比较大)次数,提高程序性能。以下是代码片段:
-
-```c++
+```cpp
int BufferList::send_l(int fd, int flags,bool udp) {
int n;
do {
@@ -412,15 +405,15 @@ int BufferList::send_l(int fd, int flags,bool udp) {
}
```
-# 批量线程切换
+## 批量线程切换
-多线程模型下,流媒体服务器在做媒体数据分发时,肯定要做线程切换。线程切换的目的一是确保线程安全,防止多条线程同时操作某个对象或资源;二是可以充分利用多核算力,防止单线程成为转发性能瓶颈。ZLMediaKit在做媒体转发时,也同样使用到线程切换来实现多线程的数据分发。但是线程切换开销也比较大,如果线程切换次数太多,将严重影响服务器性能。
+多线程模型下,流媒体服务器在做媒体数据分发时,肯定要做线程切换。线程切换的目的一是确保线程安全,防止多条线程同时操作某个对象或资源;二是可以充分利用多核算力,防止单线程成为转发性能瓶颈。ZLMediaKit 在做媒体转发时,也同样使用到线程切换来实现多线程的数据分发。但是线程切换开销也比较大,如果线程切换次数太多,将严重影响服务器性能。
-现在我们假设一个场景:RTMP推流客户端A推送一个直播到服务器,这个直播比较火爆,假设有同时10K个用户正在观看这个直播,那么我们在分发一个RTMP数据包时是否需要最多进行10K次线程切换然后再发送数据?虽然ZLMediaKit的线程切换比较轻量,但是这样频繁的线程切换也是扛不住的。
+现在我们假设一个场景:RTMP 推流客户端 A 推送一个直播到服务器,这个直播比较火爆,假设有同时 10K 个用户正在观看这个直播,那么我们在分发一个 RTMP 数据包时是否需要最多进行 10K 次线程切换然后再发送数据?虽然 ZLMediaKit 的线程切换比较轻量,但是这样频繁的线程切换也是扛不住的。
-ZLMediaKit在处理这类问题时,采用批量线程切换来尽量减少线程切换次数。假如说这10K的用户分布在32个cpu核心上,那么ZLMediaKit最多进行32次线程切换,这样ZLMediaKit将大大减少线程切换次数,同时又能使用多线程来分发数据,大大提高网络吞吐量,以下是批量线程切换代码片段:
+ZLMediaKit 在处理这类问题时,采用批量线程切换来尽量减少线程切换次数。假如说这 10K 的用户分布在 32 个 cpu 核心上,那么 ZLMediaKit 最多进行 32 次线程切换,这样 ZLMediaKit 将大大减少线程切换次数,同时又能使用多线程来分发数据,大大提高网络吞吐量,以下是批量线程切换代码片段:
-```c++
+```cpp
void emitRead(const T &in){
LOCK_GUARD(_mtx_map);
for (auto &pr : _dispatcherMap) {
@@ -446,53 +439,35 @@ void emitRead(const T &in){
reader->onRead(in);
++it;
}
- }
+ }
```
+## 采用右值引用拷贝
+ZLMediaKit 中也尽量使用右值引用拷贝来规避内存拷贝,这里就不展开论述。
-# 采用右值引用拷贝
-
-ZLMediaKit中也尽量使用右值引用拷贝来规避内存拷贝,这里就不展开论述。
+## 其他特性
-# 其他特性
+### 优化及时推流打开率
+有些应用场景需要设备端开始推流,然后 APP 立即观看的应用场景。传统的 rtmp 服务器对此应用场景是未作任何优化的,如果 APP 播放请求在推流尚未建立之前到达,那么将导致 APP 播放失败,这样视频打开成功率就会降低,用户体验很不好。
+ZLMediaKit 在针对该应用场景时,做了特别的优化;实现原理如下:
-## 优化及时推流打开率
+1、收到播放请求时,立即检查是否已经存在的媒体源,如果存在返回播放成功,否则进入第 2 步。
-有些应用场景需要设备端开始推流,然后APP立即观看的应用场景。传统的rtmp服务器对此应用场景是未作任何优化的,如果APP播放请求在推流尚未建立之前到达,那么将导致APP播放失败,这样视频打开成功率就会降低,用户体验很不好。
-
-ZLMediaKit在针对该应用场景时,做了特别的优化;实现原理如下:
-
-1、收到播放请求时,立即检查是否已经存在的媒体源,如果存在返回播放成功,否则进入第2步。
-
-2、监听对应的媒体源注册事件,同时添加播放超时定时器,并且不回复播放器然后返回。逻辑将进入第3步或第4步。
+2、监听对应的媒体源注册事件,同时添加播放超时定时器,并且不回复播放器然后返回。逻辑将进入第 3 步或第 4 步。
3、媒体源注册成功,那么立即响应播放器播放成功,同时删除播放超时定时器,并移除媒体注册事件监听。
4、超时定时器触发,响应播放器播放失败,同时删除播放超时定时器,并移除媒体注册事件监听。
-使用ZLMediaKit作为流媒体服务器,可以APP播放请求和设备端推流同时进行。
-
-
-
-# 性能测试对比
-
-目前对ZLMediaKit做了一些性能测试,查看地址:[benchmark](../test/benchmark.md)
-
-在测试时发现,ZLMediaKit在负载比较低时,其单线程性能大概是SRS的50%,单条线程大概能支撑5K个播放器,导致这个性能差距的主要原因时由于采用本地轮回网络,网络状况为理想,那么sendmsg批量发送将不起优化左右;而SRS使用了合并写特性(就是缓存300毫秒左右的数据后一次性发送),可以减少系统调用次数;如果负载比较高,以及真实网络环境下,ZLMediaKit单线程性能应该跟SRS差距更小,我们在测试报告中也能发现在客户端比较多时,ZLMediaKit单线程线程性能有比较大的提升。
-
-由于ZLMediaKit支持多线程,可以充分利用多核CPU的性能,在多核服务器上,CPU已经不再是性能瓶颈,为了减少直播延时,目前合并写特性是默认关闭的,可以通过配置文件开启。
-
-
-
-
-
-
-
-
+使用 ZLMediaKit 作为流媒体服务器,可以 APP 播放请求和设备端推流同时进行。
+## 性能测试对比
+目前对 ZLMediaKit 做了一些性能测试,查看地址:[benchmark](../test/benchmark.md)
+在测试时发现,ZLMediaKit 在负载比较低时,其单线程性能大概是 SRS 的 50%,单条线程大概能支撑 5K 个播放器,导致这个性能差距的主要原因时由于采用本地轮回网络,网络状况为理想,那么 sendmsg 批量发送将不起优化左右;而 SRS 使用了合并写特性(就是缓存 300 毫秒左右的数据后一次性发送),可以减少系统调用次数;如果负载比较高,以及真实网络环境下,ZLMediaKit 单线程性能应该跟 SRS 差距更小,我们在测试报告中也能发现在客户端比较多时,ZLMediaKit 单线程线程性能有比较大的提升。
+由于 ZLMediaKit 支持多线程,可以充分利用多核 CPU 的性能,在多核服务器上,CPU 已经不再是性能瓶颈,为了减少直播延时,目前合并写特性是默认关闭的,可以通过配置文件开启。
diff --git a/src/reference/documents/introduction_to_streaming_media_related_technologies.md b/src/reference/documents/introduction_to_streaming_media_related_technologies.md
index 448a164..e228644 100644
--- a/src/reference/documents/introduction_to_streaming_media_related_technologies.md
+++ b/src/reference/documents/introduction_to_streaming_media_related_technologies.md
@@ -1,6 +1,7 @@
---
title: 流媒体相关技术介绍
---
+
## 1、流媒体简介
**流媒体**(streaming media)是指将一连串的媒体数据压缩后,经过网络分段发送数据,在网上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如果不使用此技术,就必须在使用前下载整个媒体文件,这对于实时性要求比较高的场景而言,显然是不现实的,所以流媒体技术为此孕育而生。
@@ -17,35 +18,37 @@ title: 流媒体相关技术介绍
### 2.2 发展趋势
-由于一些互联网企业的入局,视频监控行业也在经历一系列的变局,譬如小米摄像头、360水滴摄像头的流行,也鞭策着传统的视频监控行业相关企业的变革(譬如海康威视推出的萤石云平台),虽然目前这些变革多数还局限于个人消费市场,但从长远来看,视频监控上云,是未来发展的大趋势。
+由于一些互联网企业的入局,视频监控行业也在经历一系列的变局,譬如小米摄像头、360 水滴摄像头的流行,也鞭策着传统的视频监控行业相关企业的变革(譬如海康威视推出的萤石云平台),虽然目前这些变革多数还局限于个人消费市场,但从长远来看,视频监控上云,是未来发展的大趋势。
基于云的视频监控解决方案由于其高质量、可靠性、安全性、便捷性以及较低的部署和维护成本而越来越受到人们的青睐。
-预计未来视频监控,将像目前流行的网络直播一样方便,用户安装好摄像头后,接入网络即可视频上云。使用者在浏览器或APP即可查看所有摄像头的实时监控以及历史录像,通过APP或绑定的手机号码,可以实时接收摄像头发送的事件通知(譬如入侵事件)。
+预计未来视频监控,将像目前流行的网络直播一样方便,用户安装好摄像头后,接入网络即可视频上云。使用者在浏览器或 APP 即可查看所有摄像头的实时监控以及历史录像,通过 APP 或绑定的手机号码,可以实时接收摄像头发送的事件通知(譬如入侵事件)。
### 2.3 技术难点
-由于历史原因,传统的视频监控行业技术栈多采用私有协议SDK、onvif/rtsp等协议栈。这些协议目前对浏览器而言都不友好,在以前IE浏览器还流行的时期,可以通过ocx插件的方式来对接这些协议,但是随着IE的没落以及目前流行的chrome、火狐浏览器对原生插件的愈加不友好,通过插件的方式来实现访问监控视频的方式将愈发困难。如果要在chrome、火狐浏览器上访问监控视频,目前有以下几种方案可行:
+由于历史原因,传统的视频监控行业技术栈多采用私有协议 SDK、onvif/rtsp 等协议栈。这些协议目前对浏览器而言都不友好,在以前 IE 浏览器还流行的时期,可以通过 ocx 插件的方式来对接这些协议,但是随着 IE 的没落以及目前流行的 chrome、火狐浏览器对原生插件的愈加不友好,通过插件的方式来实现访问监控视频的方式将愈发困难。如果要在 chrome、火狐浏览器上访问监控视频,目前有以下几种方案可行:
+
+- rtmp
+
+ 目前主流的 chrome 和火狐浏览器都还支持 flash 插件,所以目前在浏览器上还可以通过 rtmp 方式来访问监控视频。但是由于随着 html5 的普及以及 flash 的停止更新,预计可预见的未来,rtmp 技术将随着 flash 一起行将就木(谷歌宣布 chrom 浏览器 2020 年 12 月将不再支持 flash player)。
-- rtmp
-
-目前主流的chrome和火狐浏览器都还支持flash插件,所以目前在浏览器上还可以通过rtmp方式来访问监控视频。但是由于随着html5的普及以及flash的停止更新,预计可预见的未来,rtmp技术将随着flash一起行将就木(谷歌宣布chrom浏览器2020年12月将不再支持flash player)。
- http-flv
-
-http-flv直播的方式是一种比较新颖的方式,该技术基于html5,可以通过无插件的方式实现视频直播,而且由于rtmp负载可以平滑的转换成http-flv协议,所以正在逐渐取代rtmp成为新的直播技术标准,目前各大直播网站(譬如斗鱼直播,bilibili等)也陆续从rtmp切换成该技术。
- 但是由于浏览器的限制,不能同时打开过多(chrome限制6个)的同域名下的直播窗口,所以该技术也不太适合多路同时打开(譬如9宫格视频)的视频监控领域。而且由于Adobe的不作为,flv容器格式停止了更新,对H265的支持遥遥无期。
+
+ http-flv 直播的方式是一种比较新颖的方式,该技术基于 html5,可以通过无插件的方式实现视频直播,而且由于 rtmp 负载可以平滑的转换成 http-flv 协议,所以正在逐渐取代 rtmp 成为新的直播技术标准,目前各大直播网站(譬如斗鱼直播,bilibili 等)也陆续从 rtmp 切换成该技术。
+ 但是由于浏览器的限制,不能同时打开过多(chrome 限制 6 个)的同域名下的直播窗口,所以该技术也不太适合多路同时打开(譬如 9 宫格视频)的视频监控领域。而且由于 Adobe 的不作为,flv 容器格式停止了更新,对 H265 的支持遥遥无期。
- ws-flv
-
-ws-flv直播技术基本与http-flv一致,无非是传输`介质`换成了websocket协议,除了解除了http-flv不能同时打开过多同域名下的直播窗口的限制,其他技术特性、参数基本与http-flv一致。目前看,ws-flv既适合视频监控(可以同时打开多路监控视频)也适合视频直播行业,是rtmp很高的升级替代方案。
+
+ ws-flv 直播技术基本与 http-flv 一致,无非是传输`介质`换成了 websocket 协议,除了解除了 http-flv 不能同时打开过多同域名下的直播窗口的限制,其他技术特性、参数基本与 http-flv 一致。目前看,ws-flv 既适合视频监控(可以同时打开多路监控视频)也适合视频直播行业,是 rtmp 很高的升级替代方案。
- webrtc
-
-webrtc是谷歌主导的视频通话技术标准,目前各大主流浏览器都兼容该标准。通过该技术,用户可以在浏览器上实现无插件的视频通话,该技术也可以用于实现低延时的视频直播。目前业界也有很多基于webrtc的应用和产品,但是很多局限于视频聊天等低延时交互式场景,在视频监控领域,目前还尚未流行。而且该技术栈目前还在持续更新,技术难点太多,要与视频监控领域融合还需时日。
+
+ webrtc 是谷歌主导的视频通话技术标准,目前各大主流浏览器都兼容该标准。通过该技术,用户可以在浏览器上实现无插件的视频通话,该技术也可以用于实现低延时的视频直播。目前业界也有很多基于 webrtc 的应用和产品,但是很多局限于视频聊天等低延时交互式场景,在视频监控领域,目前还尚未流行。而且该技术栈目前还在持续更新,技术难点太多,要与视频监控领域融合还需时日。
+
- hls
-
-hls协议是苹果公司主导的技术标准,该技术标准兼容性最佳。不仅桌面浏览器,包括手机浏览器甚至是手机QQ、手机微信都支持该直播协议。
- 但是该协议延时比较大,不太适合视频监控等对延时要求很敏感的行业。不过最近苹果公司新推出低延时hls直播标准,预计hls标准将抢占更大的市场份额。
+
+ hls 协议是苹果公司主导的技术标准,该技术标准兼容性最佳。不仅桌面浏览器,包括手机浏览器甚至是手机 QQ、手机微信都支持该直播协议。
+ 但是该协议延时比较大,不太适合视频监控等对延时要求很敏感的行业。不过最近苹果公司新推出低延时 hls 直播标准,预计 hls 标准将抢占更大的市场份额。
以上直播技术标准目前都不完全契合视频监控行业的需求,如果要达到比较好的用户体验,通常以上技术混合使用。
@@ -54,42 +57,42 @@ hls协议是苹果公司主导的技术标准,该技术标准兼容性最佳
### 3.1 视频直播的现状和挑战
视频直播是近几年才兴起的产业,特别是随着游戏直播、手机直播的流行,视频直播已经司空见惯,进入了每个人的视野。
-随着阿里、腾讯等云平台的入局,OBS,SRS等优秀软件的开源,视频加速CDN技术的成熟,打赏、广告等商业模式的落地,目前视频直播产业链已经非常成熟,业界也诞生了斗鱼、虎牙、映客、花椒等知名直播平台。
+随着阿里、腾讯等云平台的入局,OBS,SRS 等优秀软件的开源,视频加速 CDN 技术的成熟,打赏、广告等商业模式的落地,目前视频直播产业链已经非常成熟,业界也诞生了斗鱼、虎牙、映客、花椒等知名直播平台。
-目前而言,这些直播平台使用的技术栈基本都是rtmp,但是由于flash技术即将被淘汰,所以直播行业也将迎来一些变局以及挑战。
-现在,基本上所有的直播平台,在web端,都已经或正在往http-flv方案转型。由于flv与rtmp同出一门(都是Adobe公司产品),负载格式一致,方案升级改造平滑可靠,http-flv替代rtmp具有天然的优势,相信将来http-flv能很好的挑起rtmp的大梁。
+目前而言,这些直播平台使用的技术栈基本都是 rtmp,但是由于 flash 技术即将被淘汰,所以直播行业也将迎来一些变局以及挑战。
+现在,基本上所有的直播平台,在 web 端,都已经或正在往 http-flv 方案转型。由于 flv 与 rtmp 同出一门(都是 Adobe 公司产品),负载格式一致,方案升级改造平滑可靠,http-flv 替代 rtmp 具有天然的优势,相信将来 http-flv 能很好的挑起 rtmp 的大梁。
### 3.2 发展趋势
-视频直播目前从内容上来讲,涵盖了游戏、美女、户外、娱乐、体育等直播;从设备上来讲,涵盖了PC、手机、web、电视等客户端,市场上也诞生了斗鱼这样的头部企业。从目前来看,视频直播行业市场格局已经比较稳固,进入了平稳发展期。
+视频直播目前从内容上来讲,涵盖了游戏、美女、户外、娱乐、体育等直播;从设备上来讲,涵盖了 PC、手机、web、电视等客户端,市场上也诞生了斗鱼这样的头部企业。从目前来看,视频直播行业市场格局已经比较稳固,进入了平稳发展期。
从技术上来讲,直播行业也将迎来一些变革。
-一是rtmp技术随着flash的一起淘汰,web端rtmp播放器将成为历史。
-二是随着webrtc的强势流行,直播技术栈可能与webrtc融合。
-三是苹果主导的低延时hls的推出,可能最终有大一统之势。
+一是 rtmp 技术随着 flash 的一起淘汰,web 端 rtmp 播放器将成为历史。
+二是随着 webrtc 的强势流行,直播技术栈可能与 webrtc 融合。
+三是苹果主导的低延时 hls 的推出,可能最终有大一统之势。
-不过近期来看,http-flv是rtmp的最佳替代方案,但是和rtmp一样,也有不支持H265的短板,而且移动端浏览器对此支持并不完善,所以该方案在将来有大概率会被其他方案替代。
+不过近期来看,http-flv 是 rtmp 的最佳替代方案,但是和 rtmp 一样,也有不支持 H265 的短板,而且移动端浏览器对此支持并不完善,所以该方案在将来有大概率会被其他方案替代。
### 3.3 技术难点
直播行业相对视频监控行业来说,商业化程度更高,更面向于普通消费者,用户规模更大,产业链也更加成熟。但是由于利益格局的划分、巨头间标准制定的角力,目前直播的技术标准和用户体验是割裂的。
-在桌面web端,之前直播技术由Adobe旗下的flash/rtmp技术主导,不过由于Adobe的不作为,以及谷歌苹果等公司的抵制,flash已经进入死亡倒计时。目前来看,http-flv已经接手rtmp的大旗,成为了新的事实上的桌面web端直播标准。但是http-flv由于其不支持H265的短板(Adobe官方可能永远也不会支持H265),其地位也并不稳固,现在也有公司正在尝试使用webrtc进行视频直播,但是由于该技术跨界太大,其技术栈又太庞杂,整个上下游产业链也并不完善,目前在直播界,还未看见大规模采用该直播技术的方案实施。
+在桌面 web 端,之前直播技术由 Adobe 旗下的 flash/rtmp 技术主导,不过由于 Adobe 的不作为,以及谷歌苹果等公司的抵制,flash 已经进入死亡倒计时。目前来看,http-flv 已经接手 rtmp 的大旗,成为了新的事实上的桌面 web 端直播标准。但是 http-flv 由于其不支持 H265 的短板(Adobe 官方可能永远也不会支持 H265),其地位也并不稳固,现在也有公司正在尝试使用 webrtc 进行视频直播,但是由于该技术跨界太大,其技术栈又太庞杂,整个上下游产业链也并不完善,目前在直播界,还未看见大规模采用该直播技术的方案实施。
-在手机APP端,由于播放技术自己可以主导,也由于历史沿革原因,目前一般沿用rtmp技术方案(需要指出的是微信小程序也支持rtmp播放器),用户体验比较好,延时一般3秒或以下。
+在手机 APP 端,由于播放技术自己可以主导,也由于历史沿革原因,目前一般沿用 rtmp 技术方案(需要指出的是微信小程序也支持 rtmp 播放器),用户体验比较好,延时一般 3 秒或以下。
-在移动web端,可采用的直播方案更少,目前基本只能采用苹果公司主导的hls方案,但是由于hls的技术特性,延时非常大(一般5秒以上,最大可达10秒以上),其观看体验跟手机APP、桌面web端是严重割裂的。
+在移动 web 端,可采用的直播方案更少,目前基本只能采用苹果公司主导的 hls 方案,但是由于 hls 的技术特性,延时非常大(一般 5 秒以上,最大可达 10 秒以上),其观看体验跟手机 APP、桌面 web 端是严重割裂的。
-通过我们上述的分析看出,目前直播技术方案,在每种端都不一样,用户体验也差距巨大,目前并没有一种多平台支持、令人满意的通用解决方案。目前要实现一个完善的直播产品,最少要采用包括rtmp/http-flv/hls这3种技术方案,而且这三种技术方案目前也并不能让人满意(rtmp/http-flv不支持H265,hls延时高)。
+通过我们上述的分析看出,目前直播技术方案,在每种端都不一样,用户体验也差距巨大,目前并没有一种多平台支持、令人满意的通用解决方案。目前要实现一个完善的直播产品,最少要采用包括 rtmp/http-flv/hls 这 3 种技术方案,而且这三种技术方案目前也并不能让人满意(rtmp/http-flv 不支持 H265,hls 延时高)。
## 4、我们的解决方案以及优势
-目前我们的流媒体服务框架支持rtsp/rtmp推流客户端,rtsp/rtmp/http-flv/ws-flv/hls播放客户端,并且可以无缝把rtsp/rtmp推流转换成上述4种播放协议,同时我们也支持mp4录制存档,必要的时候也可以从mp4文件加载成直播流。
+目前我们的流媒体服务框架支持 rtsp/rtmp 推流客户端,rtsp/rtmp/http-flv/ws-flv/hls 播放客户端,并且可以无缝把 rtsp/rtmp 推流转换成上述 4 种播放协议,同时我们也支持 mp4 录制存档,必要的时候也可以从 mp4 文件加载成直播流。
-除了上述功能之外,我们还支持拉流rtsp/rtmp代理成rtsp/rtmp/http-flv/ws-flv/hls,也支持把直播rtsp/rtmp流推送到其他的服务器。
+除了上述功能之外,我们还支持拉流 rtsp/rtmp 代理成 rtsp/rtmp/http-flv/ws-flv/hls,也支持把直播 rtsp/rtmp 流推送到其他的服务器。
-另外,我们还提供丰富的http api 以及 http hook api,通过这些api,我们可以与其他业务服务器一起,打造丰富的业务逻辑。
+另外,我们还提供丰富的 http api 以及 http hook api,通过这些 api,我们可以与其他业务服务器一起,打造丰富的业务逻辑。
-我们的流媒体框架支持linux、macos、ios、android、windows全平台,既可以作为商用的流媒体服务器,也可以移植到嵌入式设备中,作为基础流媒体服务组件。
+我们的流媒体框架支持 linux、macos、ios、android、windows 全平台,既可以作为商用的流媒体服务器,也可以移植到嵌入式设备中,作为基础流媒体服务组件。
-代码采用C++11标准打造,避免使用裸指针,稳定可靠,采用epoll多路复用、线程池、异步网络IO模式开发,并发性能优越,已经经受住了长期的高并发验证考验。同时针对及时推流的特征,做了特别的优化,可以减少视频打开延时、提高画面打开成功率,让用户获取画面秒开,延时极低的体验。
+代码采用 C++11 标准打造,避免使用裸指针,稳定可靠,采用 epoll 多路复用、线程池、异步网络 IO 模式开发,并发性能优越,已经经受住了长期的高并发验证考验。同时针对及时推流的特征,做了特别的优化,可以减少视频打开延时、提高画面打开成功率,让用户获取画面秒开,延时极低的体验。
diff --git a/src/reference/documents/rtsp_push_process.md b/src/reference/documents/rtsp_push_process.md
index 68d3005..9a285ef 100644
--- a/src/reference/documents/rtsp_push_process.md
+++ b/src/reference/documents/rtsp_push_process.md
@@ -1,10 +1,12 @@
---
title: RTSP push streaming process
---
+
# 1. The client sends an ANNOUNCE command.
+
This step primarily involves transmitting the SDP. Generally, before this command, an OPTIONS command is sent to probe the server's support for the streaming protocol. However, to reduce the number of interactions, the ANNOUNCE command can be directly sent. If not supported, the server naturally responds with an error code.
-```
+```http
ANNOUNCE rtsp://10.0.9.130:554/live/2.sdp RTSP/1.0
CSeq: 1
User-Agent: EasyPusher v1.2.16.1105
@@ -33,8 +35,10 @@ a=control:streamid=1
```
# 2. The server responds to the ANNOUNCE command.
+
If the server successfully parses the SDP, it will return a 200 code to indicate success.
-```
+
+```http
RTSP/1.0 200 OK
CSeq: 1
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -43,10 +47,10 @@ Session: KPUZ49ejotyD
```
# 3. The client sends a SETUP command.
-This command is used to negotiate the RTP transmission mode, which can be either TCP or UDP. For simplicity, it is recommended to use TCP for streaming. It should be noted that if the SDP contains multiple tracks (e.g., both audio and video), there will be multiple interactions for the SETUP command.
+This command is used to negotiate the RTP transmission mode, which can be either TCP or UDP. For simplicity, it is recommended to use TCP for streaming. It should be noted that if the SDP contains multiple tracks (e.g., both audio and video), there will be multiple interactions for the SETUP command.
-```
+```http
SETUP rtsp://10.0.9.130:554/live/2.sdp/streamid=0 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=0-1
CSeq: 2
@@ -54,8 +58,10 @@ User-Agent: EasyPusher v1.2.16.1105
```
# 4. The server responds to the SETUP command.
+
The server returns the negotiated interleaved value and other details.
-```
+
+```http
RTSP/1.0 200 OK
CSeq: 2
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -67,9 +73,10 @@ x-Transport-Options: late-tolerance=1.400000
```
# 5. The client sends a RECORD command.
+
This command is equivalent to the play command during playback. It is a synchronous command to prepare the server. Please note that, for the sake of brevity, one SETUP interaction is omitted before this command.
-```
+```http
RECORD rtsp://10.0.9.130:554/live/2.sdp RTSP/1.0
Range: npt=0.000-
CSeq: 4
@@ -78,8 +85,10 @@ Session: KPUZ49ejotyD
```
# 6. The server responds to the RECORD command, and streaming can begin!
+
After the server responds to the RECORD command, the streaming client can continuously send RTP packets.
-```
+
+```http
RTSP/1.0 200 OK
CSeq: 4
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -87,9 +96,3 @@ RTP-Info: url=rtsp://10.0.9.130:554/live/2.sdp/streamid=0,url=rtsp://10.0.9.130:
Server: ZLMediaKit-4.0(build in Mar 26 2019 17:01:17)
Session: KPUZ49ejotyD
```
-
-
-
-
-
-
diff --git a/src/reference/documents/the_nature_of_live_broadcast_delay.md b/src/reference/documents/the_nature_of_live_broadcast_delay.md
index eaec6d3..4bfc6a8 100644
--- a/src/reference/documents/the_nature_of_live_broadcast_delay.md
+++ b/src/reference/documents/the_nature_of_live_broadcast_delay.md
@@ -1,6 +1,7 @@
---
title: The Essence of Live Streaming Delay
---
+
1. Live streaming is the representation of ongoing events, generating data as time passes.
2. So why is there a delay in live streaming? The essence lies in the fact that, in order to enhance the user experience, live streaming caches a portion of historical data (such as using GOP caching to improve video loading speed).
diff --git a/src/reference/resources/README.md b/src/reference/resources/README.md
index 7df92ac..5ce8ecb 100644
--- a/src/reference/resources/README.md
+++ b/src/reference/resources/README.md
@@ -3,4 +3,5 @@ title: Resources
icon: font-awesome
index: true
---
+
diff --git a/src/reference/resources/dependency.md b/src/reference/resources/dependency.md
index 6c6e5ac..6d85098 100644
--- a/src/reference/resources/dependency.md
+++ b/src/reference/resources/dependency.md
@@ -4,18 +4,18 @@ title: Dependency and Copyright
## I. ZLMediaKit's List of Dependent Libraries
-| Dependent Components | License Type | Remarks | Project Address |
-| :--------------------------: | :----------: | :----------------------------------------------------------: | :----------------------------------------------------: |
-| ZLToolKit | MIT | Strong dependency, ZLToolKit also partially depends on some open-source codes | https://github.com/ZLMediaKit/ZLToolKit |
-| ireader/media-server | MIT | Default dependency, can be removed when ENABLE_HLS, ENABLE_MP4, ENABLE_RTPPROXY are set to disabled at compile time | https://github.com/ireader/media-server |
-| jsoncpp | MIT | MediaServer dependency | https://github.com/open-source-parsers/jsoncpp |
-| openssl | Apache-2.0 | Dependency when enabling SSL and WebRTC related features, can be removed when ENABLE_OPENSSL, ENABLE_WEBRTC are set to disabled at compile time | https://github.com/openssl/openssl |
-| srtp | Similar to MIT | Dependency when enabling WebRTC related features, can be removed when ENABLE_WEBRTC is set to disabled at compile time | https://github.com/cisco/libsrtp |
-| usrsctp | BSD-3-Clause | Dependency when enabling WebRTC datachannel related features, can be removed when ENABLE_SCTP is set to disabled at compile time | https://github.com/sctplab/usrsctp |
-| mediasoup | ISC | Some WebRTC source code extracted from mediasoup, can be removed when ENABLE_WEBRTC is set to disabled at compile time | https://github.com/versatica/mediasoup |
-| ffmpeg | GPL/LGPL | There's minor dependency with the transcoding branch and mk_api, can be removed when ENABLE_FFMPEG is set to disabled at compile time, default is disabled | https://github.com/FFmpeg/FFmpeg |
-| wepoll | Similar to MIT | Dependency when ENABLE_WPOLL is enabled during Windows compilation, default is disabled | https://github.com/piscisaureus/wepoll |
-| SPSParser | | sps/pps related parsing code, originated from a friend, modified, initially extracted from ffmpeg, copyright doubtful | https://github.com/ZLMediaKit/ZLMediaKit/blob/master/src/Extension/SPSParser.h |
+| Dependent Components | License Type | Remarks | Project Address |
+| :------------------: | :------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
+| ZLToolKit | MIT | Strong dependency, ZLToolKit also partially depends on some open-source codes | https://github.com/ZLMediaKit/ZLToolKit |
+| ireader/media-server | MIT | Default dependency, can be removed when ENABLE_HLS, ENABLE_MP4, ENABLE_RTPPROXY are set to disabled at compile time | https://github.com/ireader/media-server |
+| jsoncpp | MIT | MediaServer dependency | https://github.com/open-source-parsers/jsoncpp |
+| openssl | Apache-2.0 | Dependency when enabling SSL and WebRTC related features, can be removed when ENABLE_OPENSSL, ENABLE_WEBRTC are set to disabled at compile time | https://github.com/openssl/openssl |
+| srtp | Similar to MIT | Dependency when enabling WebRTC related features, can be removed when ENABLE_WEBRTC is set to disabled at compile time | https://github.com/cisco/libsrtp |
+| usrsctp | BSD-3-Clause | Dependency when enabling WebRTC datachannel related features, can be removed when ENABLE_SCTP is set to disabled at compile time | https://github.com/sctplab/usrsctp |
+| mediasoup | ISC | Some WebRTC source code extracted from mediasoup, can be removed when ENABLE_WEBRTC is set to disabled at compile time | https://github.com/versatica/mediasoup |
+| ffmpeg | GPL/LGPL | There's minor dependency with the transcoding branch and mk_api, can be removed when ENABLE_FFMPEG is set to disabled at compile time, default is disabled | https://github.com/FFmpeg/FFmpeg |
+| wepoll | Similar to MIT | Dependency when ENABLE_WPOLL is enabled during Windows compilation, default is disabled | https://github.com/piscisaureus/wepoll |
+| SPSParser | | sps/pps related parsing code, originated from a friend, modified, initially extracted from ffmpeg, copyright doubtful | https://github.com/ZLMediaKit/ZLMediaKit/blob/master/src/Extension/SPSParser.h |
## II. Other Dependencies
@@ -25,12 +25,13 @@ title: Dependency and Copyright
- Dependency on libmysql-clinet when enabling mysql connection pool feature, default is disabled.
## III. ZLToolkit Related Dependencies
+
- [getopt](https://github.com/ZLMediaKit/ZLToolKit/tree/master/src/win32) is a command-line parsing tool for Windows, not needed for other platforms.
- [uv_errno](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/uv_errno.h) some error handling code is derived from libuv.
- [strptime_win](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/strptime_win.cpp) is the strptime porting function code for Windows, sourced from the internet, origin unknown.
- [mini](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/mini.h)
- is sourced from [github](https://github.com/r-lyeh-archived/mINI), after arrangement and modification.
+is sourced from [github](https://github.com/r-lyeh-archived/mINI), after arrangement and modification.
- [function_traits](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/function_traits.h) is sourced from the internet, likely from Qi Yu.
- [base64](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/base64.h) is sourced from the internet, modified, likely originated from ffmpeg.
diff --git a/src/reference/resources/rtmp_support_for_h265_and_opus.md b/src/reference/resources/rtmp_support_for_h265_and_opus.md
index cd54f12..91ab817 100644
--- a/src/reference/resources/rtmp_support_for_h265_and_opus.md
+++ b/src/reference/resources/rtmp_support_for_h265_and_opus.md
@@ -1,15 +1,19 @@
---
title: RTMP supports H265 and OPUS
---
+
## Background
+
RTMP/FLV is the de facto standard in the live streaming industry, and they are widely used in the domestic live streaming field. To achieve plugin-free low-latency live streaming playback in web browsers, RTMP/FLV is essential.
Since RTMP/FLV is a proprietary protocol designed by Adobe, it does not natively support H.265 (widely used in video surveillance applications) and Opus (widely used in RTC applications). However, there is a growing demand for live streaming infrastructure in the video surveillance and RTC industries. Therefore, it is important to modify RTMP to add support for H.265 and Opus.
## Implementation Approach
+
RTMP determines the encoding format through codec ID and distinguishes data types (including audio packets and video packets) through message type. Therefore, the codec_id for audio and video can be the same as long as they are of the same type and do not conflict.
For example, the codec ID for H.264 is 7, and the codec ID for G.711A is also 7.
Currently, the default codec ID for H.265 in China is **12** (implemented and published by [金山云](https://github.com/ksvc/FFmpeg/wiki)).
As for the RTMP extension for Opus, there is currently no widespread consensus. After discussions with relevant individuals, the author has negotiated and defined its codec ID as **13**. The modification has already been implemented for FFmpeg (based on the latest version) to add support for[h265/opus RTMP extension](https://gitee.com/xia-chu/FFmpeg).
## Server Implementation
+
ZLMediaKit has already implemented comprehensive support for H.265/Opus in RTSP/RTMP/MP4/HLS. Feel free to test and use it.
diff --git a/src/reference/resources/video_conferencing_related_resources.md b/src/reference/resources/video_conferencing_related_resources.md
index d950cba..4228f2f 100644
--- a/src/reference/resources/video_conferencing_related_resources.md
+++ b/src/reference/resources/video_conferencing_related_resources.md
@@ -1,13 +1,14 @@
---
title: Video Conference Related Resources
---
+
- [Random Tech Talking](https://www.bilibili.com/video/BV1AK411R7NG/)
- - Related materials:[webrtc over tcp](https://user-images.githubusercontent.com/11495632/204230234-04da9d84-ffc7-4d32-bda3-04c72474205f.png)、[webrtc over udp](https://user-images.githubusercontent.com/11495632/204230272-13448d78-b6da-40f2-94b9-da517fa5cc0b.png)、[webrtc时序图](https://user-images.githubusercontent.com/11495632/204230325-1b395c6f-c094-414d-9d4e-8ea04120eed6.png)。
-- WebRTC
- - [ZLMediaKit Source Code Explanation 1](https://www.bilibili.com/video/BV1kq4y1u7cN/)
- - [ZLMediaKit Source Code Explanation 2](https://www.bilibili.com/video/BV1SR4y1t7V4/)
- - [ZLMediaKit webrtc Usage Demonstration](https://www.bilibili.com/video/BV1Eg411N7TJ/)
- - [ZLMediaKit webrtc Implementation](https://www.bilibili.com/video/BV1uL4y1i7KP/)
+ - Related materials:[webrtc over tcp](https://user-images.githubusercontent.com/11495632/204230234-04da9d84-ffc7-4d32-bda3-04c72474205f.png)、[webrtc over udp](https://user-images.githubusercontent.com/11495632/204230272-13448d78-b6da-40f2-94b9-da517fa5cc0b.png)、[webrtc 时序图](https://user-images.githubusercontent.com/11495632/204230325-1b395c6f-c094-414d-9d4e-8ea04120eed6.png)。
+- WebRTC
+ - [ZLMediaKit Source Code Explanation 1](https://www.bilibili.com/video/BV1kq4y1u7cN/)
+ - [ZLMediaKit Source Code Explanation 2](https://www.bilibili.com/video/BV1SR4y1t7V4/)
+ - [ZLMediaKit webrtc Usage Demonstration](https://www.bilibili.com/video/BV1Eg411N7TJ/)
+ - [ZLMediaKit webrtc Implementation](https://www.bilibili.com/video/BV1uL4y1i7KP/)
diff --git a/src/reference/resources/zltoolkit_source_code_study_notes.md b/src/reference/resources/zltoolkit_source_code_study_notes.md
index 8d0a2dd..d1c365b 100644
--- a/src/reference/resources/zltoolkit_source_code_study_notes.md
+++ b/src/reference/resources/zltoolkit_source_code_study_notes.md
@@ -1,4 +1,5 @@
---
title: ZLToolKit source code study notes
---
+
[zltoolkit source code analysis](https://blog.csdn.net/youlezhe/category_11460699.html)
diff --git a/src/reference/test/benchmark.md b/src/reference/test/benchmark.md
index a2a5214..c8d49c5 100644
--- a/src/reference/test/benchmark.md
+++ b/src/reference/test/benchmark.md
@@ -1,45 +1,56 @@
---
title: Benchmark
---
-# Note
-This test is severely outdated and is not indicative.
-# Test Environment
+::: note This test is severely outdated and is not indicative.
+
+:::
+
+## Test Environment
+
- System: Linux core 3.16.0-7-amd64 #1 SMP Debian 3.16.59-1 (2018-10-03) x86_64 GNU/Linux
- Memory: 15GB
- CPU: Intel(R) Xeon(R) CPU E3-1220 v5 @ 3.00GHz; 4 cores
- Network: Gigabit Ethernet
- The test is conducted by accessing the server through a loopback network on the test client.
-# Test Tools
+## Test Tools
+
ZLMeidaKit comes with a test benchmark program called test_benchmark, which uses a single-process multi-threaded model.
-# Test Server
+## Test Server
+
ZLMeidaKit includes a test server called test_server, which supports RTSP/RTMP/HLS protocols and uses a multi-threaded model.
-# Test Media Stream
+## Test Media Stream
+
The test_server pulls an RTMP stream `rtmp://live.hkstv.hk.lxdns.com/live/hks1` and then forwards it using the test_server. The approximate bitrate of the stream is around 300-400 Kbit/s.
-# Test Results
+## Test Results
+
+::: note
-Note: When building with CMake, use the command `cmake .. -DCMAKE_BUILD_TYPE=Release` to compile the optimized version.
+When building with CMake, use the command `cmake .. -DCMAKE_BUILD_TYPE=Release` to compile the optimized version.
+
+:::
| Number of Players (RTMP) | CPU (Max 400%) | Memory (VIRT/RES) | Bandwidth (Average) | Packet Loss |
-| --- | --- | --- | --- | --- |
-| 1000 | 20% | 702M/13M | 40 MByte/s | None |
-| 2000 | 39% | 702M/18M | 80 MByte/s | None |
-| 5000 | 92% | 702M/32M | 200 MByte/s | None |
-| 10000 | 170% | 702M/59M | 400 MByte/s | None |
+| ------------------------ | -------------- | ----------------- | ------------------- | ----------- |
+| 1000 | 20% | 702M/13M | 40 MByte/s | None |
+| 2000 | 39% | 702M/18M | 80 MByte/s | None |
+| 5000 | 92% | 702M/32M | 200 MByte/s | None |
+| 10000 | 170% | 702M/59M | 400 MByte/s | None |
| Number of Players (RTSP/TCP) | CPU (Max 400%) | Memory (VIRT/RES) | Bandwidth (Average) | Packet Loss |
-| --- | --- | --- | --- | --- |
-| 1000 | 18% | 702M/13M | 42 MByte/s | None |
-| 2000 | 35% | 702M/19M | 82 MByte/s | None |
-| 5000 | 80% | 702M/35M | 198 MByte/s | None |
-| 10000 | 130% | 702M/62M | 405 MByte/s | None |
+| ---------------------------- | -------------- | ----------------- | ------------------- | ----------- |
+| 1000 | 18% | 702M/13M | 42 MByte/s | None |
+| 2000 | 35% | 702M/19M | 82 MByte/s | None |
+| 5000 | 80% | 702M/35M | 198 MByte/s | None |
+| 10000 | 130% | 702M/62M | 405 MByte/s | None |
+
+## Comparison with SRS Performance
-# Comparison with SRS Performance
| Number of Players (RTMP) | CPU (Max 400%) | Memory (VIRT/RES) | Bandwidth (Average) | Packet Loss |
-| --- | --- | --- | --- | --- |
-| 1000 | 10% | 310M/53M | 41.17 MByte/s | None |
-| 2000 | 18% | 604M/117M | 83.86 MByte/s | None |
+| ------------------------ | -------------- | ----------------- | ------------------- | ----------- |
+| 1000 | 10% | 310M/53M | 41.17 MByte/s | None |
+| 2000 | 18% | 604M/117M | 83.86 MByte/s | None |
diff --git a/src/reference/test/delay_test.md b/src/reference/test/delay_test.md
index 72d37ae..9a2866d 100644
--- a/src/reference/test/delay_test.md
+++ b/src/reference/test/delay_test.md
@@ -2,20 +2,27 @@
title: Delay Testing
---
-## Note
+::: note
+
This test was conducted earlier, and some content may have become outdated. The `ultraLowDelay` configuration option has been removed. To achieve the lowest delay mode, set the combined write delay to 0 (default is 0). When testing the delay, you can use WebRTC playback.
+:::
+
## Network Environment
- - `localhost`
+
+- `localhost`
## Operating System
- - `macOS`
-
+
+- `macOS`
+
## Server
+
- `MediaServer`, startup parameter `-t 1`, single-threaded startup
- Open the configuration file and enable `ultraLowDelay` mode
## Streaming Software
+
- `obs`, RTMP streaming to localhost
- `Rate Control`: `CBR`
- `Bitrate`: 2500
@@ -26,32 +33,36 @@ This test was conducted earlier, and some content may have become outdated. The
- `Tune`: `zerolatency`
- `Resolution`: 1280x720
- `FPS`: 30
-![image](https://user-images.githubusercontent.com/11495632/64311220-daf53f00-cfd5-11e9-8d1f-c39d95c335c4.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311220-daf53f00-cfd5-11e9-8d1f-c39d95c335c4.png)
## Player
- - Built-in `test_player`
- - Play RTSP (test both UDP and TCP modes) or RTMP on localhost
+
+- Built-in `test_player`
+- Play RTSP (test both UDP and TCP modes) or RTMP on localhost
## Testing Method
- - Open a browser and go to the online stopwatch webpage https://miaobiao.51240.com/
- - Configure OBS to capture the stopwatch section of the browser image and start streaming to MediaServer
- - Open the test_player and play the corresponding RTSP or RTMP URL
- - Use a screenshot tool to capture the frames and compare the time difference between the online stopwatch webpage and the test_player
+
+- Open a browser and go to the online stopwatch webpage https://miaobiao.51240.com/
+- Configure OBS to capture the stopwatch section of the browser image and start streaming to MediaServer
+- Open the test_player and play the corresponding RTSP or RTMP URL
+- Use a screenshot tool to capture the frames and compare the time difference between the online stopwatch webpage and the test_player
## Test Results
- - RTMP playback, delay of 200ms to 400ms
-![image](https://user-images.githubusercontent.com/11495632/64311009-0af01280-cfd5-11e9-9117-2f520db0b70f.png)
-![image](https://user-images.githubusercontent.com/11495632/64311040-2b1fd180-cfd5-11e9-8526-675d5d40d746.png)
- - RTSP playback (TCP mode), delay of 200ms to 400ms
- ![image](https://user-images.githubusercontent.com/11495632/64311126-76d27b00-cfd5-11e9-89e4-59e9cb15b8bc.png)
- ![image](https://user-images.githubusercontent.com/11495632/64311161-9b2e5780-cfd5-11e9-96dd-5ab7eecc83ca.png)
+- RTMP playback, delay of 200ms to 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311009-0af01280-cfd5-11e9-9117-2f520db0b70f.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311040-2b1fd180-cfd5-11e9-8526-675d5d40d746.png)
- - RTSP playback (UDP mode), delay of 200ms to 400ms
-![image](https://user-images.githubusercontent.com/11495632/64311179-b600cc00-cfd5-11e9-953f-07e73c377df1.png)
-![image](https://user-images.githubusercontent.com/11495632/64311187-c022ca80-cfd5-11e9-89b4-a015d614706e.png)
+- RTSP playback (TCP mode), delay of 200ms to 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311126-76d27b00-cfd5-11e9-89e4-59e9cb15b8bc.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311161-9b2e5780-cfd5-11e9-96dd-5ab7eecc83ca.png)
+
+- RTSP playback (UDP mode), delay of 200ms to 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311179-b600cc00-cfd5-11e9-953f-07e73c377df1.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311187-c022ca80-cfd5-11e9-89b4-a015d614706e.png)
## Test Conclusion
+
- In the single-threaded mode, where the player and streaming software are in the same thread without any thread switching, the delay is slightly more stable and lower.
- Enabling TCP_NODELAY and disabling MSG_MORE did not significantly optimize the delay in this test.
- The average delay from multiple screenshots is around 300ms, with a minimum of around 200ms and a maximum of over 400ms.
diff --git a/src/reference/test/how_to_test_delay.md b/src/reference/test/how_to_test_delay.md
index 308377d..51cb6f1 100644
--- a/src/reference/test/how_to_test_delay.md
+++ b/src/reference/test/how_to_test_delay.md
@@ -1,10 +1,13 @@
---
title: How to test the delay?
---
+
## Introduction
+
Some users often ask me in the group why there is a several seconds delay when using ZLMediaKit for stream playback or stream forwarding. Sometimes, the delay can be as long as more than 10 seconds or even half a minute for HLS. The purpose of this article is to clarify the misunderstanding about delay.
## What is Delay
+
Many users do not fully understand what delay means. They think that the time difference between the displayed frames of any player and the original stream frames is the delay, but this is actually the biggest misconception about delay.
Delay is not superficial. Many people are not professional when testing delay and have insufficient understanding of the professionalism of delay testing. I would like to remind everyone that not every player is qualified to perform delay testing!
@@ -12,38 +15,38 @@ In summary, the overall delay consists of the following components:
- **Capture Delay**
-When capturing camera or graphics card frames, there is a certain delay in capturing the frames as YUV/RGB data due to limitations such as fps, CPU performance, and memory copying speed. Generally, the delay is in the millisecond range. Since general encoders have restrictions on input data formats, such as requiring consistent input of YUV420P, there will also be a delay in the conversion calculation when converting RGB to YUV420P (this can be reduced using the libyuv library). In general, the capture delay is about milliseconds. If the fps is 30, the capture delay will generally be more than 30 milliseconds, and there may be additional milliseconds of delay during memory copying and color conversion.
+ When capturing camera or graphics card frames, there is a certain delay in capturing the frames as YUV/RGB data due to limitations such as fps, CPU performance, and memory copying speed. Generally, the delay is in the millisecond range. Since general encoders have restrictions on input data formats, such as requiring consistent input of YUV420P, there will also be a delay in the conversion calculation when converting RGB to YUV420P (this can be reduced using the libyuv library). In general, the capture delay is about milliseconds. If the fps is 30, the capture delay will generally be more than 30 milliseconds, and there may be additional milliseconds of delay during memory copying and color conversion.
- **Encoding Delay**
-When inputting the original frames into the encoder, the encoded data is not immediately output, especially when B-frames are enabled. Since B-frames require referencing the following P-frames, the delay will be greater. Therefore, in delay-sensitive situations, B-frames are generally not enabled, and in such cases, the encoding delay should be in the millisecond range and not very high.
+ When inputting the original frames into the encoder, the encoded data is not immediately output, especially when B-frames are enabled. Since B-frames require referencing the following P-frames, the delay will be greater. Therefore, in delay-sensitive situations, B-frames are generally not enabled, and in such cases, the encoding delay should be in the millisecond range and not very high.
- **Upstream Network Transmission Delay**
-After the data is encoded, it needs to be packed into a certain protocol before being written to the socket and transmitted to the streaming server or stream proxy server. Protocol packing involves a certain amount of memory copying and computation, which can increase the delay. However, this delay is very small and can be basically ignored. When uploading data to the server, this delay can be large or small, depending on the network quality.
+ After the data is encoded, it needs to be packed into a certain protocol before being written to the socket and transmitted to the streaming server or stream proxy server. Protocol packing involves a certain amount of memory copying and computation, which can increase the delay. However, this delay is very small and can be basically ignored. When uploading data to the server, this delay can be large or small, depending on the network quality.
- **Server Protocol Conversion Delay**
-After the server receives the data, it needs to perform operations such as reading socket buffer, protocol parsing, demultiplexing, and repacking. However, overall, this delay is relatively small and has little impact. Sometimes, to improve performance, the server may use a mechanism of batching writes, which means that it will forward the data only after receiving a certain amount of data. This delay is generally a few hundred milliseconds, with ZLMediaKit defaulting to around 300 milliseconds. However, ZLMediaKit has this batching write feature disabled by default, so this delay is also very small.
+ After the server receives the data, it needs to perform operations such as reading socket buffer, protocol parsing, demultiplexing, and repacking. However, overall, this delay is relatively small and has little impact. Sometimes, to improve performance, the server may use a mechanism of batching writes, which means that it will forward the data only after receiving a certain amount of data. This delay is generally a few hundred milliseconds, with ZLMediaKit defaulting to around 300 milliseconds. However, ZLMediaKit has this batching write feature disabled by default, so this delay is also very small.
- **Downstream Network Delay**
-When streaming media forwards video data to the player, there will be a delay caused by network transmission, the size of which depends on the network quality. When low-latency mode is disabled in ZLMediaKit, there will also be additional delay due to the use of MSG_MORE and the disabling of TCP_NODELAY, but low-latency mode is enabled by default in ZLMediaKit.
+ When streaming media forwards video data to the player, there will be a delay caused by network transmission, the size of which depends on the network quality. When low-latency mode is disabled in ZLMediaKit, there will also be additional delay due to the use of MSG_MORE and the disabling of TCP_NODELAY, but low-latency mode is enabled by default in ZLMediaKit.
- **Player Delay**
-Player delay consists of network reception delay, protocol parsing and demultiplexing delay, decoding delay, cache delay, and rendering delay. Among these delays, the **cache delay** is the largest. In order to ensure smooth video playback in case of network jitter, general players increase the delay by adding playback buffers. This way, when the network deteriorates, the playback buffering can prevent video stuttering. Moreover, in order to achieve audio-video synchronization, a certain amount of buffering must be ensured. This type of delay is generally in the seconds range, typically around 5 seconds.
+ Player delay consists of network reception delay, protocol parsing and demultiplexing delay, decoding delay, cache delay, and rendering delay. Among these delays, the **cache delay** is the largest. In order to ensure smooth video playback in case of network jitter, general players increase the delay by adding playback buffers. This way, when the network deteriorates, the playback buffering can prevent video stuttering. Moreover, in order to achieve audio-video synchronization, a certain amount of buffering must be ensured. This type of delay is generally in the seconds range, typically around 5 seconds.
- **Player GOP Cache Delay**
-To display the video immediately, streaming media servers often cache the most recent I-frame, and all subsequent audio-video data after this I-frame is referred to as the GOP (Group of Pictures) cache. If the GOP is not cached, the player has to wait for the next I-frame to successfully decode the video or avoid screen flickering. Obviously, to improve the playback experience, this GOP cache cannot be eliminated. Generally, the GOP duration can be as short as 1-3 seconds or as long as tens of seconds, depending on the settings of the capture-side encoder, which the server cannot change. However, since general players do not discard too many frames after receiving the cache to ensure low latency, and players also want to have a certain amount of buffering to ensure smooth playback, this GOP cache will increase the player's delay.
+ To display the video immediately, streaming media servers often cache the most recent I-frame, and all subsequent audio-video data after this I-frame is referred to as the GOP (Group of Pictures) cache. If the GOP is not cached, the player has to wait for the next I-frame to successfully decode the video or avoid screen flickering. Obviously, to improve the playback experience, this GOP cache cannot be eliminated. Generally, the GOP duration can be as short as 1-3 seconds or as long as tens of seconds, depending on the settings of the capture-side encoder, which the server cannot change. However, since general players do not discard too many frames after receiving the cache to ensure low latency, and players also want to have a certain amount of buffering to ensure smooth playback, this GOP cache will increase the player's delay.
- **Overall Delay**
-The sum of all the aforementioned delays is the perceived delay you observe. Sowhen you see a delay in stream playback or stream forwarding using ZLMediaKit, it is a combination of all these factors. It's important to understand that some delays are inherent to the streaming process and cannot be completely eliminated. However, there are ways to optimize the delay and minimize its impact.
-
+ The sum of all the aforementioned delays is the perceived delay you observe. Sowhen you see a delay in stream playback or stream forwarding using ZLMediaKit, it is a combination of all these factors. It's important to understand that some delays are inherent to the streaming process and cannot be completely eliminated. However, there are ways to optimize the delay and minimize its impact.
## How to Test Delay
+
Testing delay with general players like VLC is unprofessional. The delay in these players is at least in the order of seconds. In order to achieve smooth playback and audio/video synchronization, these players cannot provide you with real-time delay data.
Here, I strongly recommend that you write your own bufferless player to test the delay. However, this is obviously beyond the ability of most people. Therefore, ZLMediaKit provides a simple player for testing delay:
@@ -57,8 +60,8 @@ ffplay -i rtmp://xxxxxxx -fflags nobuffer
If you don't know how to install ffplay, you can download a precompiled version from [here](http://ffmpeg.org/download.html).
-
## More Information About Delay
+
[The Essence of Live Broadcast Delay](../documents/the_nature_of_live_broadcast_delay.md)
[Delay-related Testing](./delay_test.md)
diff --git a/src/reference/test/online_test.md b/src/reference/test/online_test.md
index 4032165..6eea795 100644
--- a/src/reference/test/online_test.md
+++ b/src/reference/test/online_test.md
@@ -1,7 +1,9 @@
---
title: Online test
---
+
## Testing Url
+
- http/hls/http-flv/ws-flv: http://zlmediakit.com:8888/
- https: https://zlmediakit.com/
- rtsp: zlmediakit.com:554
@@ -9,5 +11,6 @@ title: Online test
- GB28181 UDP/TCP: zlmediakit.com:10000
## Start testing
+
[Push test](../../guide/media_server/push_test.md)
[Play test](../../guide/media_server/play_url_rules.md)
diff --git a/src/reference/test/performance_testing.md b/src/reference/test/performance_testing.md
index e61ccd2..11c85d0 100644
--- a/src/reference/test/performance_testing.md
+++ b/src/reference/test/performance_testing.md
@@ -1,9 +1,10 @@
---
title: Performance Testing
---
-# 1. Latest Performance Test:
-## 1.1 Test Environment
+## 1. Latest Performance Test:
+
+### 1.1 Test Environment
- CPU: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz, 4 cores, 8 threads
- Operating System: CentOS release 6.3 (Final)
@@ -13,33 +14,36 @@ title: Performance Testing
- Compiler: gcc (GCC) 8.2.0
- Compilation Type: Release
-## 1.2 Test Data
+### 1.2 Test Data
> There were inaccuracies in the memory usage during the push streaming performance test (due to a multi-GOP caching bug at the time of testing).
| Client Type | Stream Count | CPU | Memory | Network IO | Theoretical Performance of 4 Physical Cores |
-| :---------: | :----------: | :--: | :----: | :--------: | :---------------------------------------: |
-| RTSP Play | 20K | 160% | 203M | 5Gb/s | Approximately 100K |
-| RTSP Play | 32.2K | 235% | 220M | 7.78Gb/s | Approximately 100K |
-| RTSP Push | 10K | 264% | 760M | 2.39Gb/s | Approximately 30K |
-| | | | | | |
-| RTMP Play | 10K | 148% | 81M | 2.33Gb/s | Approximately 50K |
-| RTMP Play | 30K | 450% | 246M | 7Gb/s | Approximately 50K |
-| RTMP Push | 10K | 224% | 1.6G | 2.16Gb/s | Approximately 30K |
-
-## 1.3 Detailed Test Data
+| :---------: | :----------: | :--: | :----: | :--------: | :-----------------------------------------: |
+| RTSP Play | 20K | 160% | 203M | 5Gb/s | Approximately 100K |
+| RTSP Play | 32.2K | 235% | 220M | 7.78Gb/s | Approximately 100K |
+| RTSP Push | 10K | 264% | 760M | 2.39Gb/s | Approximately 30K |
+| | | | | | |
+| RTMP Play | 10K | 148% | 81M | 2.33Gb/s | Approximately 50K |
+| RTMP Play | 30K | 450% | 246M | 7Gb/s | Approximately 50K |
+| RTMP Push | 10K | 224% | 1.6G | 2.16Gb/s | Approximately 30K |
+
+### 1.3 Detailed Test Data
+
- [RTMP Pull Stream](./rtmp_pull_stream_performance_test.md)
- [RTMP Push Stream](./rtmp_push_stream_performance_test.md)
- [RTSP Pull Stream](./rtsp_pull_stream_performance_test.md)
- [RTSP Push Stream](./rtsp_push_stream_performance_test.md)
-# 2. Earlier Performance Test Records
+## 2. Earlier Performance Test Records
+
- [RTMP Pull Stream Performance Test](https://github.com/ZLMediaKit/ZLMediaKit/issues/406)
- [GB28181 Performance Test](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
- [RTSP Audio Pull Stream Performance Test](https://github.com/ZLMediaKit/ZLMediaKit/issues/1271)
- [Outdated Performance Test Records](./benchmark.md)
-# 3. Performance Testing and Optimization
+## 3. Performance Testing and Optimization
+
- [RTSP Performance Optimization and Testing](../development_log/rtsp_performance_optimization.md)
- [HLS Performance Optimization and Testing](../development_log/hls_high_performance_journey.md)
- [RTMP Performance Optimization](https://github.com/ZLMediaKit/ZLMediaKit/issues/540)
diff --git a/src/reference/test/rtmp_pull_stream_performance_test.md b/src/reference/test/rtmp_pull_stream_performance_test.md
index 0e19448..45267cf 100644
--- a/src/reference/test/rtmp_pull_stream_performance_test.md
+++ b/src/reference/test/rtmp_pull_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtmp pull stream performance test
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtmp pull stream performance test
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtmp拉流性能测试(1万路)
+## 二、rtmp 拉流性能测试(1 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,23 +73,22 @@ ulimit -n 102400
./test_bench_pull -c 10000 -i rtmp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169045558-bcf711b8-b27c-4372-a1d2-ccb0e1a33d65.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169045971-ebf7da67-00f1-4c63-8c17-3c27937a5016.png)
-- nload信息(平均2.34Gb/s):
+- nload 信息(平均 2.34Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169046147-39376f04-471b-4de2-a345-0e41982a612b.png)
-
-# 三、rtmp拉流性能测试(3万路)
+## 三、rtmp 拉流性能测试(3 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -91,20 +96,14 @@ ulimit -n 102400
./test_bench_pull -c 30000 -i rtmp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169049433-97174931-5f6b-45db-a320-0c4257b37fad.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169049184-951a7108-c3e6-451f-97c9-164abf439ed2.png)
-
-- nload信息(平均7.09Gb/s):
+- nload 信息(平均 7.09Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169049082-cf6c665f-b876-4e7d-91d6-391b10ec2b52.png)
-
-
-
-
diff --git a/src/reference/test/rtmp_push_stream_performance_test.md b/src/reference/test/rtmp_push_stream_performance_test.md
index 79b5c92..7f42fa6 100644
--- a/src/reference/test/rtmp_push_stream_performance_test.md
+++ b/src/reference/test/rtmp_push_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtmp push stream performance test
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtmp push stream performance test
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtmp推流性能测试(1万路)
+## 二、rtmp 推流性能测试(1 万路)
- 推流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,24 +73,14 @@ ulimit -n 102400
./test_bench_push -i rtmp://127.0.0.1/live/test -c 10000 -o rtmp://127.0.0.1/live/push
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169197952-9a042459-a3fe-4b48-903b-4aa0095dfe77.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198018-1a823b57-4e9f-4331-950d-329178c40de8.png)
-
-- nload信息(平均2.16Gb/s):
+- nload 信息(平均 2.16Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169198085-5c4278f1-c4dc-421a-992c-aac94d090479.png)
-
-
-
-
-
-
-
-
diff --git a/src/reference/test/rtsp_pull_stream_performance_test.md b/src/reference/test/rtsp_pull_stream_performance_test.md
index e0f8c15..88a4000 100644
--- a/src/reference/test/rtsp_pull_stream_performance_test.md
+++ b/src/reference/test/rtsp_pull_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtsp pull stream performance test
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtsp pull stream performance test
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtsp拉流性能测试(2万路)
+## 二、rtsp 拉流性能测试(2 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,25 +73,22 @@ ulimit -n 102400
./test_bench_pull -c 20000 -i rtsp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169055524-10ec0ab2-23a2-4103-b2c4-0c5affb61b85.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169055647-1c3599a8-63e6-4d08-8179-69e74eed05e4.png)
-
-- nload信息(平均5Gb/s):
+- nload 信息(平均 5Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169055992-16e0c2a6-58db-4683-912a-6e7f94783350.png)
-
-
-# 三、rtsp拉流性能测试(4万路)
+## 三、rtsp 拉流性能测试(4 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -93,27 +96,17 @@ ulimit -n 102400
./test_bench_pull -c 40000 -i rtsp://127.0.0.1/live/test
```
-- 发现由于随机端口不够,有些播放器掉线(只剩32244个):
-![图片](https://user-images.githubusercontent.com/11495632/169060039-9bfddd5c-62d3-4ddf-8c20-176e7ab4c8b0.png)
+- 发现由于随机端口不够,有些播放器掉线(只剩 32244 个):
+ ![图片](https://user-images.githubusercontent.com/11495632/169060039-9bfddd5c-62d3-4ddf-8c20-176e7ab4c8b0.png)
-
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169059095-d15b9645-e80e-40ba-a607-31896b90db0c.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169059190-f4bcae26-c037-49c5-a4c0-002f4d96847f.png)
-- nload信息(平均7.78Gb/s):
+- nload 信息(平均 7.78Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169059778-2c525923-75e5-4935-b489-817249941c6a.png)
-
-
-
-
-
-
-
-
diff --git a/src/reference/test/rtsp_push_stream_performance_test.md b/src/reference/test/rtsp_push_stream_performance_test.md
index 05ab9d9..ca103b5 100644
--- a/src/reference/test/rtsp_push_stream_performance_test.md
+++ b/src/reference/test/rtsp_push_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtsp push stream performance test
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtsp push stream performance test
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtsp推流性能测试(1万路)
+## 二、rtsp 推流性能测试(1 万路)
- 推流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,28 +73,14 @@ ulimit -n 102400
./test_bench_push -i rtmp://127.0.0.1/live/test -c 10000 -o rtsp://127.0.0.1/live/push
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198621-85d3a0f3-ffc4-4e2d-bdb8-8e886130ff2e.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198658-7ca9599c-16da-4dd9-8fb5-aa35d35cbe97.png)
-
-- nload信息(平均2.39Gb/s):
+- nload 信息(平均 2.39Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169198759-7baa33a2-30fe-409b-a0bf-e737be849ad1.png)
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/tutorial/README.md b/src/tutorial/README.md
index 925430b..f032a13 100644
--- a/src/tutorial/README.md
+++ b/src/tutorial/README.md
@@ -3,22 +3,22 @@ title: Tutorial
icon: lightbulb
description: This tutorial will guide you through the process of compiling and running ZLMediaKit.
---
+
## 1. Obtain the Source Code
**Please refrain from downloading the source code in zip package format directly from GitHub**. Instead, you should clone the ZLMediaKit code using git. This is due to ZLMediaKit's reliance on multiple third-party project codes which are not included in the zip package. Follow these steps to do this:
- ```bash
- # It's recommended for users in China to download from the synchronized mirror site, gitee
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- # Remember to execute this command
- git submodule update --init
- ```
+```bash
+# It's recommended for users in China to download from the synchronized mirror site, gitee
+git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+cd ZLMediaKit
+# Remember to execute this command
+git submodule update --init
+```
## 2. Strongly Recommended
-If you're a beginner, we highly recommend compiling ZLMediaKit using Ubuntu16 or later versions. macOS is the second recommended platform. The least recommended platforms are CentOS6.* and Windows.
-
+If you're a beginner, we highly recommend compiling ZLMediaKit using Ubuntu16 or later versions. macOS is the second recommended platform. The least recommended platforms are CentOS6.\* and Windows.
zlmediakit has been launched on vcpkg, please refer to [install zlmediakit using vcpkg](../guide/install/install_zlmediakit_using_vcpkg.md) for convenient installation.
@@ -32,8 +32,6 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
- On macOS, clang >= ??? (it's uncertain, but most likely won't encounter any issues)
- On Windows, Visual Studio >= 2015 (some versions of VS2013 can also compile, but for a smoother experience, VS2017 is recommended)
-
-
### 3.2. Installing the Compiler
- If you're using a Debian-based operating system (including Ubuntu), the built-in gcc version is usually recent enough. Here's how to install the gcc compiler:
@@ -49,7 +47,7 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
sudo yum -y install gcc-c++
```
-- If you're a CentOS6.* user, you can install the gcc compiler this way:
+- If you're a CentOS6.\* user, you can install the gcc compiler this way:
```bash
sudo yum install centos-release-scl -y
@@ -62,8 +60,6 @@ ZLMediaKit utilizes C++11 syntax and libraries, hence, it's required that your c
- If you're a Windows user, it's recommended to install VS2017 or later versions.
-
-
## 4. CMake
ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile (or Xcode/VS project), so you must install CMake to complete the subsequent steps.
@@ -80,7 +76,7 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
sudo yum -y install cmake
```
-- If you're a CentOS6.* user, then you need to download the new version of cmake source code and then compile and install cmake:
+- If you're a CentOS6.\* user, then you need to download the new version of cmake source code and then compile and install cmake:
```bash
wget https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3.tar.gz
@@ -91,8 +87,6 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
sudo make install
```
-
-
- If you're a macOS user, here's how you can install cmake:
```bash
@@ -104,11 +98,10 @@ ZLMediaKit uses CMake to build the project. CMake is needed to generate Makefile
```bash
# Install win64 version of cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win64-x64.zip
-
+
# Install win32 version of cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win32-x86.zip
```
-
## 5. Dependencies
@@ -143,7 +136,7 @@ Most of the third-party libraries that ZLMediaKit depends on are optional. Durin
sudo apt-get install ffmpeg
```
-- Users of centos6.* can refer to this [article](https://blog.51cto.com/mengix/2452395).
+- Users of centos6.\* can refer to this [article](https://blog.51cto.com/mengix/2452395).
- To install dependencies on macOS/CentOS:
@@ -157,7 +150,7 @@ Most of the third-party libraries that ZLMediaKit depends on are optional. Durin
## 6. Building and Compiling the Project
-The activation of webrtc related features is complex and is not enabled for compilation by default. If you are
+The activation of webrtc related features is complex and is not enabled for compilation by default. If you are
interested in the webrtc feature of zlmediakit, you can refer to [here](../guide/protocol/webrtc/webrtc_compilation_and_use.md).
- On Linux or macOS systems, you should operate as follows:
@@ -183,15 +176,11 @@ interested in the webrtc feature of zlmediakit, you can refer to [here](../guide
- If you are using VS2017 or earlier, you need to use cmake-gui to generate the VS project and then compile:
- ```sh
1 Enter the ZLMediaKit directory and execute git submodule update --init to download the code of ZLToolKit
-
-
- 2 Use cmake-gui to open the project and generate the vs project file.
- 3 Locate the project file (ZLMediaKit.sln), double-click to open with vs2017.
- 4 Choose to compile the Release version.
- 5 Locate the target file and run the test case.
- ```
+ 2 Use cmake-gui to open the project and generate the vs project file.
+ 3 Locate the project file (ZLMediaKit.sln), double-click to open with vs2017.
+ 4 Choose to compile the Release version.
+ 5 Locate the target file and run the test case.
- Also, you can refer to [here](../guide/install/compilation_instructions_for_windows_version.md) for Windows compilation.
@@ -256,9 +245,7 @@ The ZLMediaKit project mainly generates three types of binary target files, whic
- On Windows:
```sh
- ZLMediaKit
-
-/release/windows/Debug/mk_api.dll
+ ZLMediaKit/release/windows/Debug/mk_api.dll
ZLMediaKit/release/windows/Debug/mk_api.lib
```
diff --git a/src/zh/README.md b/src/zh/README.md
index c0404fc..8d76c17 100644
--- a/src/zh/README.md
+++ b/src/zh/README.md
@@ -4,8 +4,6 @@ icon: home
title: 首页
description: 一个基于C++11的高性能运营级流媒体服务框架.
heroImage: /logo.png
-bgImage:
-bgImageDark:
bgImageStyle:
background-attachment: fixed
heroText: ZLMediaKit
@@ -22,8 +20,6 @@ highlights:
- header: 特性
description: 该项目是一个商用级流媒体服务器流媒体解决方案,其中包括移动嵌入式跨平台支持以及网络编程二次开发SDK.
image: /assets/image/features.svg
- bgImage:
- bgImageDark:
bgImageStyle:
background-repeat: repeat
background-size: initial
@@ -31,80 +27,65 @@ highlights:
- title: c++11开发
icon: bug-slash
details: 采用C++11开发,避免使用原始指针,提供稳定可靠的代码和卓越的性能.
- link:
- title: 支持多种协议
icon: box-archive
details: 支持多种协议(RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV/GB28181/HTTP-TS/WebSocket-TS/HTTP-fMP4/WebSocket-fMP4/MP4/WebRTC)与协议间互相转换
- link:
- title: 高并发与高性能
icon: bolt
details: 采用多路复用/多线程/异步网络IO模型开发,提供卓越的并发性能,支持海量客户端连接.
- link:
- title: 稳定可靠的生产环境使用
icon: microscope
details: 代码经过广泛的稳定性和性能测试,在生产环境中得到广泛应用.
- link:
- title: 跨平台兼容性
icon: linux
details: 支持包括Linux、macOS、iOS、Android和Windows在内的所有主要平台.
- link:
- title: 多指令集平台支持
icon: microchip
details: 支持多种指令集平台,如x86、arm、risc-v、mips、龙芯和申威.
- link:
- title: 极速启动和低延迟
icon: truck-fast
details: 提供极速启动,极低延迟(在500毫秒以内,甚至可以低至100毫秒),提供优异的用户体验.
- link:
- title: 用于集成的C API
icon: code
details: 提供全面的标准C API,可用作SDK或被其他语言调用.
- link:
- title: 完整的媒体服务器解决方案
icon: server
details: 提供完整的媒体服务器,可直接部署为商用服务器,无需额外开发.
- link:
- title: RESTful API和Web Hook
icon: file-code
details: 提供完整的RESTful API和Web Hook,支持丰富的业务逻辑.
- link:
- title: 视频监控桥接
icon: video
details: 打通了视频监控协议栈与直播协议栈,对RTSP/RTMP支持都很完善.
- link:
- title: 完善的编解码器支持
icon: box-open
details: 全面支持H265/H264/AAC/G711/OPUS.
- link:
- title: 高级功能
icon: toolbox
details: 功能完善,支持集群、按需转协议、按需推拉流、先播后推、断连续推等功能.
- link:
- title: 极致性能和可扩展性
icon: chart-pie
details: 极致性能,支持单台机器上的10W级播放器和100Gb/s级IO带宽能力.
- link:
- title: 独家功能
icon: user-secret
details: 全面支持IPv6网络,并通过独家功能提供终极用户体验.
- link:
-
copyright: false
-footer: Theme by VuePress Theme Hope | MIT Licensed,
+footer:
+ Theme by VuePress Theme Hope | MIT Licensed,
Copyright © 2019-present ZLMediaKit
---
diff --git a/src/zh/guide/README.md b/src/zh/guide/README.md
index 15907a2..e038533 100644
--- a/src/zh/guide/README.md
+++ b/src/zh/guide/README.md
@@ -1,52 +1,51 @@
---
title: 指南
icon: terminal
-
---
-# 一个基于C++11的高性能运营级流媒体服务框架
-
+## 一个基于 C++11 的高性能运营级流媒体服务框架
-[![](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/ZLMediaKit/ZLMediaKit/blob/master/LICENSE)
-[![](https://img.shields.io/badge/language-c++-red.svg)](https://en.cppreference.com/)
-[![](https://img.shields.io/badge/platform-linux%20|%20macos%20|%20windows-blue.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://img.shields.io/badge/PRs-welcome-yellow.svg)](https://github.com/ZLMediaKit/ZLMediaKit/pulls)
+[![badge](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/ZLMediaKit/ZLMediaKit/blob/master/LICENSE)
+[![badge](https://img.shields.io/badge/language-c++-red.svg)](https://en.cppreference.com/)
+[![badge](https://img.shields.io/badge/platform-linux%20|%20macos%20|%20windows-blue.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://img.shields.io/badge/PRs-welcome-yellow.svg)](https://github.com/ZLMediaKit/ZLMediaKit/pulls)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/android.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/linux.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/macos.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/windows.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/android.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/linux.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/macos.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/windows.yml/badge.svg)](https://github.com/ZLMediaKit/ZLMediaKit)
-[![](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/docker.yml/badge.svg)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
-[![](https://img.shields.io/docker/pulls/zlmediakit/zlmediakit)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
+[![badge](https://github.com/ZLMediaKit/ZLMediaKit/actions/workflows/docker.yml/badge.svg)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
+[![badge](https://img.shields.io/docker/pulls/zlmediakit/zlmediakit)](https://hub.docker.com/r/zlmediakit/zlmediakit/tags)
## 项目特点
-- 基于C++11开发,避免使用裸指针,代码稳定可靠,性能优越。
+- 基于 C++11 开发,避免使用裸指针,代码稳定可靠,性能优越。
- 支持多种协议(RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV/GB28181/HTTP-TS/WebSocket-TS/HTTP-fMP4/WebSocket-fMP4/MP4/WebRTC),支持协议互转。
-- 使用多路复用/多线程/异步网络IO模式开发,并发性能优越,支持海量客户端连接。
+- 使用多路复用/多线程/异步网络 IO 模式开发,并发性能优越,支持海量客户端连接。
- 代码经过长期大量的稳定性、性能测试,已经在线上商用验证已久。
-- 支持linux、macos、ios、android、windows全平台。
-- 支持x86、arm、risc-v、mips、龙芯、申威等指令集平台。
-- 支持画面秒开、极低延时([500毫秒内,最低可达100毫秒](../reference/test/delay_test.md))。
-- 提供完善的标准[C API](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include),可以作SDK用,或供其他语言调用。
+- 支持 linux、macos、ios、android、windows 全平台。
+- 支持 x86、arm、risc-v、mips、龙芯、申威等指令集平台。
+- 支持画面秒开、极低延时([500 毫秒内,最低可达 100 毫秒](../reference/test/delay_test.md))。
+- 提供完善的标准[C API](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include),可以作 SDK 用,或供其他语言调用。
- 提供完整的[MediaServer](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/server)服务器,可以免开发直接部署为商用服务器。
- 提供完善的[restful api](./media_server/restful_api.md)以及[web hook](./media_server/web_hook_api.md),支持丰富的业务逻辑。
-- 打通了视频监控协议栈与直播协议栈,对RTSP/RTMP支持都很完善。
-- 全面支持H265/H264/AAC/G711/OPUS。
+- 打通了视频监控协议栈与直播协议栈,对 RTSP/RTMP 支持都很完善。
+- 全面支持 H265/H264/AAC/G711/OPUS。
- 功能完善,支持集群、按需转协议、按需推拉流、先播后推、断连续推等功能。
-- 极致性能,单机10W级别播放器,100Gb/s级别io带宽能力。
+- 极致性能,单机 10W 级别播放器,100Gb/s 级别 io 带宽能力。
- 极致体验,[独家特性](../reference/documents/exclusive_features.md)
-- [谁在使用zlmediakit?](https://github.com/ZLMediaKit/ZLMediaKit/issues/511)
-- 全面支持ipv6网络
+- [谁在使用 zlmediakit?](https://github.com/ZLMediaKit/ZLMediaKit/issues/511)
+- 全面支持 ipv6 网络
## 项目定位
- 移动嵌入式跨平台流媒体解决方案。
- 商用级流媒体服务器。
-- 网络编程二次开发SDK。
+- 网络编程二次开发 SDK。
## 功能清单
+
### 功能一览
```mermaid
@@ -88,121 +87,123 @@ flowchart TD
FMP4_LIVE-->WEBSOCKET_FMP4_P(WEBSOCKET-FMP4)
```
-- RTSP[S]
- - RTSP[S] 服务器,支持RTMP/MP4/HLS转RTSP[S],支持亚马逊echo show这样的设备
- - RTSP[S] 播放器,支持RTSP代理,支持生成静音音频
- - RTSP[S] 推流客户端与服务器
- - 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种RTP传输方式
- - 服务器/客户端完整支持Basic/Digest方式的登录鉴权,全异步可配置化的鉴权接口
- - 支持H265编码
- - 服务器支持RTSP推流(包括`rtp over udp` `rtp over tcp`方式)
- - 支持H264/H265/AAC/G711/OPUS/MJPEG编码,其他编码能转发但不能转协议
-
-- RTMP[S]
- - RTMP[S] 播放服务器,支持RTSP/MP4/HLS转RTMP
- - RTMP[S] 发布服务器,支持录制发布流
- - RTMP[S] 播放器,支持RTMP代理,支持生成静音音频
- - RTMP[S] 推流客户端
- - 支持http[s]-flv直播服务器
- - 支持http[s]-flv直播播放器
- - 支持websocket-flv直播
- - 支持H264/H265/AAC/G711/OPUS编码,其他编码能转发但不能转协议
+- RTSP\[S]
+
+ - RTSP\[S] 服务器,支持 RTMP/MP4/HLS 转 RTSP\[S] ,支持亚马逊 echo show 这样的设备
+ - RTSP\[S] 播放器,支持 RTSP 代理,支持生成静音音频
+ - RTSP\[S] 推流客户端与服务器
+ - 支持 `rtp over udp` `rtp over tcp` `rtp over http` `rtp组播` 四种 RTP 传输方式
+ - 服务器/客户端完整支持 Basic/Digest 方式的登录鉴权,全异步可配置化的鉴权接口
+ - 支持 H265 编码
+ - 服务器支持 RTSP 推流(包括`rtp over udp` `rtp over tcp`方式)
+ - 支持 H264/H265/AAC/G711/OPUS/MJPEG 编码,其他编码能转发但不能转协议
+
+- RTMP\[S]
+
+ - RTMP\[S] 播放服务器,支持 RTSP/MP4/HLS 转 RTMP
+ - RTMP\[S] 发布服务器,支持录制发布流
+ - RTMP\[S] 播放器,支持 RTMP 代理,支持生成静音音频
+ - RTMP\[S] 推流客户端
+ - 支持 http\[S] -flv 直播服务器
+ - 支持 http\[S] -flv 直播播放器
+ - 支持 websocket-flv 直播
+ - 支持 H264/H265/AAC/G711/OPUS 编码,其他编码能转发但不能转协议
- 支持[RTMP-H265](https://github.com/ksvc/FFmpeg/wiki)
- 支持[RTMP-OPUS](../reference/resources/rtmp_support_for_h265_and_opus.md)
- 支持[enhanced-rtmp(H265)](https://github.com/veovera/enhanced-rtmp)
- HLS
- - 支持HLS文件(mpegts/fmp4)生成,自带HTTP文件服务器
- - 通过cookie追踪技术,可以模拟HLS播放为长连接,可以实现HLS按需拉流、播放统计等业务
- - 支持HLS播发器,支持拉流HLS转rtsp/rtmp/mp4
- - 支持H264/H265/AAC/G711/OPUS编码
-
+ - 支持 HLS 文件(mpegts/fmp4)生成,自带 HTTP 文件服务器
+ - 通过 cookie 追踪技术,可以模拟 HLS 播放为长连接,可以实现 HLS 按需拉流、播放统计等业务
+ - 支持 HLS 播发器,支持拉流 HLS 转 rtsp/rtmp/mp4
+ - 支持 H264/H265/AAC/G711/OPUS 编码
- TS
- - 支持http[s]-ts直播
- - 支持ws[s]-ts直播
- - 支持H264/H265/AAC/G711/OPUS编码
-
+ - 支持 http\[S] -ts 直播
+ - 支持 ws\[S] -ts 直播
+ - 支持 H264/H265/AAC/G711/OPUS 编码
- fMP4
- - 支持http[s]-fmp4直播
- - 支持ws[s]-fmp4直播
- - 支持H264/H265/AAC/G711/OPUS/MJPEG编码
-- HTTP[S]与WebSocket
+ - 支持 http\[S] -fmp4 直播
+ - 支持 ws\[S] -fmp4 直播
+ - 支持 H264/H265/AAC/G711/OPUS/MJPEG 编码
+
+- HTTP\[S] 与 WebSocket
+
- 服务器支持`目录索引生成`,`文件下载`,`表单提交请求`
- 客户端提供`文件下载器(支持断点续传)`,`接口请求器`,`文件上传器`
- - 完整HTTP API服务器,可以作为web后台开发框架
+ - 完整 HTTP API 服务器,可以作为 web 后台开发框架
- 支持跨域访问
- - 支持http客户端、服务器cookie
- - 支持WebSocket服务器和客户端
- - 支持http文件访问鉴权
-
-- GB28181与RTP推流
- - 支持UDP/TCP RTP(PS/TS/ES)推流服务器,可以转换成RTSP/RTMP/HLS等协议
- - 支持RTSP/RTMP/HLS等协议转rtp推流客户端,支持TCP/UDP模式,提供相应restful api,支持主动被动方式
- - 支持H264/H265/AAC/G711/OPUS编码
- - 支持es/ps/ts/ehome rtp推流
- - 支持es/ps rtp转推
- - 支持GB28181主动拉流模式
+ - 支持 http 客户端、服务器 cookie
+ - 支持 WebSocket 服务器和客户端
+ - 支持 http 文件访问鉴权
+
+- GB28181 与 RTP 推流
+
+ - 支持 UDP/TCP RTP(PS/TS/ES)推流服务器,可以转换成 RTSP/RTMP/HLS 等协议
+ - 支持 RTSP/RTMP/HLS 等协议转 rtp 推流客户端,支持 TCP/UDP 模式,提供相应 restful api,支持主动被动方式
+ - 支持 H264/H265/AAC/G711/OPUS 编码
+ - 支持 es/ps/ts/ehome rtp 推流
+ - 支持 es/ps rtp 转推
+ - 支持 GB28181 主动拉流模式
- 支持双向语音对讲
-- MP4点播与录制
- - 支持录制为FLV/HLS/MP4
- - RTSP/RTMP/HTTP-FLV/WS-FLV支持MP4文件点播,支持seek
- - 支持H264/H265/AAC/G711/OPUS编码
-
+- MP4 点播与录制
+ - 支持录制为 FLV/HLS/MP4
+ - RTSP/RTMP/HTTP-FLV/WS-FLV 支持 MP4 文件点播,支持 seek
+ - 支持 H264/H265/AAC/G711/OPUS 编码
- WebRTC
- - 支持WebRTC推流,支持转其他协议
- - 支持WebRTC播放,支持其他协议转WebRTC
- - 支持双向echo test
- - 支持simulcast推流
- - 支持上下行rtx/nack丢包重传
+ - 支持 WebRTC 推流,支持转其他协议
+ - 支持 WebRTC 播放,支持其他协议转 WebRTC
+ - 支持双向 echo test
+ - 支持 simulcast 推流
+ - 支持上下行 rtx/nack 丢包重传
- **支持单端口、多线程、客户端网络连接迁移(开源界唯一)**。
- - 支持TWCC rtcp动态调整码率
- - 支持remb/pli/sr/rr rtcp
- - 支持rtp扩展解析
- - 支持GOP缓冲,webrtc播放秒开
- - 支持datachannel
- - 支持webrtc over tcp模式
- - 优秀的nack、jitter buffer算法, 抗丢包能力卓越
- - 支持whip/whep协议
-- [SRT支持](./protocol/srt/README.md)
+ - 支持 TWCC rtcp 动态调整码率
+ - 支持 remb/pli/sr/rr rtcp
+ - 支持 rtp 扩展解析
+ - 支持 GOP 缓冲,webrtc 播放秒开
+ - 支持 datachannel
+ - 支持 webrtc over tcp 模式
+ - 优秀的 nack、jitter buffer 算法, 抗丢包能力卓越
+ - 支持 whip/whep 协议
+- [SRT 支持](./protocol/srt/README.md)
- 其他
- - 支持丰富的restful api以及web hook事件
- - 支持简单的telnet调试
+ - 支持丰富的 restful api 以及 web hook 事件
+ - 支持简单的 telnet 调试
- 支持配置文件热加载
- 支持流量统计、推拉流鉴权等事件
- 支持虚拟主机,可以隔离不同域名
- 支持按需拉流,无人观看自动关断拉流
- 支持先播放后推流,提高及时推流画面打开率
- - 提供完整强大的c api sdk
- - 支持FFmpeg拉流代理任意格式的流
- - 支持http api生成并返回实时截图
- - 支持按需解复用、转协议,当有人观看时才开启转协议,降低cpu占用率
- - 支持溯源模式的集群部署,溯源方式支持rtsp/rtmp/hls/http-ts, 边沿站支持hls, 源站支持多个(采用round robin方式溯源)
- - rtsp/rtmp/webrtc推流异常断开后,可以在超时时间内重连推流,播放器无感知
-
+ - 提供完整强大的 c api sdk
+ - 支持 FFmpeg 拉流代理任意格式的流
+ - 支持 http api 生成并返回实时截图
+ - 支持按需解复用、转协议,当有人观看时才开启转协议,降低 cpu 占用率
+ - 支持溯源模式的集群部署,溯源方式支持 rtsp/rtmp/hls/http-ts, 边沿站支持 hls, 源站支持多个(采用 round robin 方式溯源)
+ - rtsp/rtmp/webrtc 推流异常断开后,可以在超时时间内重连推流,播放器无感知
## 编译以及测试
-**编译前务必仔细参考wiki:[快速开始](../tutorial/README.md)操作!!!**
+
+**编译前务必仔细参考 wiki:[快速开始](../tutorial/README.md)操作!!!**
## 怎么使用
- 你有三种方法使用ZLMediaKit,分别是:
+你有三种方法使用 ZLMediaKit,分别是:
- - 1、使用c api,作为sdk使用,请参考[这里](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include).
- - 2、作为独立的流媒体服务器使用,不想做c/c++开发的,可以参考 [restful api](./media_server/restful_api.md) 和 [web hook](./media_server/web_hook_api.md).
- - 3、如果想做c/c++开发,添加业务逻辑增加功能,可以参考这里的[测试程序](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/tests).
+- 1、使用 c api,作为 sdk 使用,请参考[这里](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/api/include).
+- 2、作为独立的流媒体服务器使用,不想做 c/c++开发的,可以参考 [restful api](./media_server/restful_api.md) 和 [web hook](./media_server/web_hook_api.md).
+- 3、如果想做 c/c++开发,添加业务逻辑增加功能,可以参考这里的[测试程序](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/tests).
## Docker 镜像
-你可以从Docker Hub下载已经编译好的镜像并启动它:
+你可以从 Docker Hub 下载已经编译好的镜像并启动它:
```bash
#此镜像为github持续集成自动编译推送,跟代码(master分支)保持最新状态
docker run -id -p 1935:1935 -p 8080:80 -p 8443:443 -p 8554:554 -p 10000:10000 -p 10000:10000/udp -p 8000:8000/udp -p 9000:9000/udp zlmediakit/zlmediakit:master
```
-你也可以根据Dockerfile编译镜像:
+你也可以根据 Dockerfile 编译镜像:
```bash
bash build_docker_images.sh
diff --git a/src/zh/guide/code/oncetoken.md b/src/zh/guide/code/oncetoken.md
index aa94b44..2905d87 100644
--- a/src/zh/guide/code/oncetoken.md
+++ b/src/zh/guide/code/oncetoken.md
@@ -2,11 +2,12 @@
title: 代码篇之onceToken
---
-ZLMediaKit里面大量用到了一个名叫`onceToken`对象, 很多小伙伴对这个工具类不明就里,下面我在此解释下其作用:
-onceToken 主要使用C/C++的RAII思想,确保在变量构造和析构时执行自定义代码;主要应用场景有如下:
+ZLMediaKit 里面大量用到了一个名叫`onceToken`对象, 很多小伙伴对这个工具类不明就里,下面我在此解释下其作用:
+onceToken 主要使用 C/C++的 RAII 思想,确保在变量构造和析构时执行自定义代码;主要应用场景有如下:
- 1、作为全局变量用,在程序加载时执行特定代码,例如生成默认配置文件:
-```C++
+
+```cpp
////////////HLS相关配置///////////
namespace Hls {
#define HLS_FIELD "hls."
@@ -22,56 +23,57 @@ const string kFileBufSize = HLS_FIELD"fileBufSize";
const string kFilePath = HLS_FIELD"filePath";
onceToken token([](){
- mINI::Instance()[kSegmentDuration] = 2;
- mINI::Instance()[kSegmentNum] = 3;
- mINI::Instance()[kSegmentRetain] = 5;
- mINI::Instance()[kFileBufSize] = 64 * 1024;
- mINI::Instance()[kFilePath] = "./www";
+ mINI::Instance()[kSegmentDuration] = 2;
+ mINI::Instance()[kSegmentNum] = 3;
+ mINI::Instance()[kSegmentRetain] = 5;
+ mINI::Instance()[kFileBufSize] = 64 * 1024;
+ mINI::Instance()[kFilePath] = "./www";
},nullptr);
} //namespace Hls
```
-- 2、作为static变量,确保代码只执行一次:
-```C++
+- 2、作为 static 变量,确保代码只执行一次:
+
+```cpp
int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
- typedef void (HttpSession::*HttpCMDHandle)(int64_t &);
- static unordered_map s_func_map;
- static onceToken token([]() {
- s_func_map.emplace("GET",&HttpSession::Handle_Req_GET);
- s_func_map.emplace("POST",&HttpSession::Handle_Req_POST);
- }, nullptr);
+ typedef void (HttpSession::*HttpCMDHandle)(int64_t &);
+ static unordered_map s_func_map;
+ static onceToken token([]() {
+ s_func_map.emplace("GET",&HttpSession::Handle_Req_GET);
+ s_func_map.emplace("POST",&HttpSession::Handle_Req_POST);
+ }, nullptr);
- //后续代码省略
+ //后续代码省略
}
```
- 3、作为局部变量,确保函数退出前做一些清理工作,例如释放锁:
-```C++
+
+```cpp
template
bool emitEvent(const string &strEvent,ArgsType &&...args){
- onceToken token([&] {
- //上锁,记录锁定线程id
- _mtxListener.lock();
- if(_lock_depth++ == 0){
- _lock_thread = this_thread::get_id();
- }
- }, [&]() {
- //释放锁,取消锁定线程id
- if(--_lock_depth == 0){
- _lock_thread = thread::id();
- if(_map_moved){
- //还原_mapListener
- _map_moved = false;
- _mapListener = std::move(_mapListenerTemp);
- }
- }
- _mtxListener.unlock();
- });
+ onceToken token([&] {
+ //上锁,记录锁定线程id
+ _mtxListener.lock();
+ if(_lock_depth++ == 0){
+ _lock_thread = this_thread::get_id();
+ }
+ }, [&]() {
+ //释放锁,取消锁定线程id
+ if(--_lock_depth == 0){
+ _lock_thread = thread::id();
+ if(_map_moved){
+ //还原_mapListener
+ _map_moved = false;
+ _mapListener = std::move(_mapListenerTemp);
+ }
+ }
+ _mtxListener.unlock();
+ });
- //后续代码省略
+ //后续代码省略
}
```
-- 4、这个对象取名源自pthread_once以及ios下的dispatch_once。
-
+- 4、这个对象取名源自 pthread_once 以及 ios 下的 dispatch_once。
diff --git a/src/zh/guide/faq/not_recommended_qq.md b/src/zh/guide/faq/not_recommended_qq.md
index 971bb34..8a122ff 100644
--- a/src/zh/guide/faq/not_recommended_qq.md
+++ b/src/zh/guide/faq/not_recommended_qq.md
@@ -1,25 +1,22 @@
---
title: 为什么不建议QQ私聊咨询问题?
---
+
## 为什么不建议私聊
-- 1、QQ私聊不好追溯和整理,很难形成文档,很多重复问题, 不能对项目有所益处。
+- 1、QQ 私聊不好追溯和整理,很难形成文档,很多重复问题, 不能对项目有所益处。
-- 2、QQ沟通效率其实很低下,虽然能回答及时,但是提问门槛太低,提问者不够重视,往往需要回答者循环渐进引导才能大体把问题说清楚,这样很浪费时间。
+- 2、QQ 沟通效率其实很低下,虽然能回答及时,但是提问门槛太低,提问者不够重视,往往需要回答者循环渐进引导才能大体把问题说清楚,这样很浪费时间。
-- 3、QQ私聊消息不定时,很容易中断回答者当前工作进程,而github issue可以统一处理,这样更节约时间。
+- 3、QQ 私聊消息不定时,很容易中断回答者当前工作进程,而 github issue 可以统一处理,这样更节约时间。
-- 4、QQ私聊其他用户不能参与回答,别人也看不到问题和答案,不利于思维发散和知识传播。
+- 4、QQ 私聊其他用户不能参与回答,别人也看不到问题和答案,不利于思维发散和知识传播。
## 一般只接受以下无私交友谊关系人员的私聊技术咨询
-- 1、提交过pr或其他形式的代码
-- 2、开源过基于zlmediakit的项目
-- 3、在qq群或issue上热心解答过相关技术问题
-- 4、分享过自写的zlmediakit相关文档
-- 5、赞助过zlmediakit项目或本人
-- 6、做过一切对zlmediakit发展和推广有贡献的事情
-
-
-
-
+- 1、提交过 pr 或其他形式的代码
+- 2、开源过基于 zlmediakit 的项目
+- 3、在 qq 群或 issue 上热心解答过相关技术问题
+- 4、分享过自写的 zlmediakit 相关文档
+- 5、赞助过 zlmediakit 项目或本人
+- 6、做过一切对 zlmediakit 发展和推广有贡献的事情
diff --git a/src/zh/guide/faq/rtmp_playback_compatibility_issues.md b/src/zh/guide/faq/rtmp_playback_compatibility_issues.md
index 2678ce3..afdcbc8 100644
--- a/src/zh/guide/faq/rtmp_playback_compatibility_issues.md
+++ b/src/zh/guide/faq/rtmp_playback_compatibility_issues.md
@@ -2,23 +2,22 @@
title: RTMP播放兼容性问题
---
-一般来说 rtmp的规范是 先发送metadata ,然后发送config帧,然后发送关键帧 然后是普通帧
+一般来说 rtmp 的规范是 先发送 metadata ,然后发送 config 帧,然后发送关键帧 然后是普通帧
-config帧收到后就能初始化解码器了
+config 帧收到后就能初始化解码器了
-但是有些流不太一样,并没有收到视频的config帧就收到其他帧了
+但是有些流不太一样,并没有收到视频的 config 帧就收到其他帧了
-这个时候视频Track并没创建和初始化
+这个时候视频 Track 并没创建和初始化
-初步怀疑是nginx的rtmp服务器兼容性不好
+初步怀疑是 nginx 的 rtmp 服务器兼容性不好
-zlm的推流器会严格按照先发送metadata ,然后发送config帧,然后发送关键帧 然后是普通帧的流程来做
+zlm 的推流器会严格按照先发送 metadata ,然后发送 config 帧,然后发送关键帧 然后是普通帧的流程来做
-也会缓存所有的config帧
+也会缓存所有的 config 帧
-ffplay能播放成功是因为它是根据数据量和时间来判断播放成功
+ffplay 能播放成功是因为它是根据数据量和时间来判断播放成功
只要数据量达到一定量或者时间达到一定时间 就会触发播放成功的事件
这样做的好处是 播放成功率高 坏处是打开视频时间长
-
diff --git a/src/zh/guide/install/compilation_instructions_for_windows_version.md b/src/zh/guide/install/compilation_instructions_for_windows_version.md
index f141202..05eb9d0 100644
--- a/src/zh/guide/install/compilation_instructions_for_windows_version.md
+++ b/src/zh/guide/install/compilation_instructions_for_windows_version.md
@@ -1,12 +1,13 @@
---
title: Windows 版编译说明
---
+
# 基于 scoop + vcpkg 的 Windows 版编译说明
以下为基于 [scoop](https://github.com/lukesampson/scoop) + [vcpkg](https://github.com/microsoft/vcpkg) 编译 `ZLMediaKit` 的一种方式.
-* `scoop`: Windows 命令行下使用的软件包安装管理工具;
-* `vcpkg`: 微软发起的 C++ 库管理器, 其中有大量常用开源库;
+- `scoop`: Windows 命令行下使用的软件包安装管理工具;
+- `vcpkg`: 微软发起的 C++ 库管理器, 其中有大量常用开源库;
由于可以在命令行下使用, 可以非常方便的进行自动化集成. 推荐大家试用.
@@ -23,23 +24,32 @@ title: Windows 版编译说明
具体可参考其官网说明, 以下仅列出相关简要步骤.
1. 设置环境变量 `SCOOP`, 用于配置 `scoop` 的下载安装目录(包括其管理的软件包):
- ```
+
+ ```sh
$env:SCOOP = 'C:\work\develop\scoop'
```
+
1. 为当前用户设置允许执行 `powershell` 脚本:
- ```
+
+ ```sh
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
+
1. 安装 `scoop`:
- ```
+
+ ```sh
iwr -useb get.scoop.sh | iex
```
+
1. 为 `scoop` 添加 `extras` 软件仓库:
- ```
+
+ ```sh
scoop bucket add extras
```
+
1. 安装 `cmake` 及 `ninja`:
- ```
+
+ ```sh
scoop install cmake ninja
```
@@ -52,19 +62,26 @@ title: Windows 版编译说明
`vcpkg` 具体使用可参考[官方说明](https://github.com/microsoft/vcpkg), [官方说明中文版](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md).
1. 下载 `vcpkg`, 其中包括各种配置脚本以及开源库的编译脚本, 下载路径假设为: `C:\work\develop`, 执行:
- ```
+
+ ```sh
git clone https://github.com/microsoft/vcpkg
```
+
1. 下载预编译的 `vcpkg` 包管理工具:
- ```
+
+ ```sh
.\vcpkg\bootstrap-vcpkg.bat -disableMetrics
```
+
1. 编译 `openssl`:
- ```
+
+ ```sh
.\vcpkg\vcpkg.exe install --triplet=x64-windows-static openssl
```
+
1. 编译 `libsrtp`, 需要 `ENABLE_OPENSSL`, 可编辑 `C:\work\develop\vcpkg\ports\libsrtp\portfile.cmake`, 修改 `vcpkg_configure_cmake` 为如下:
- ```
+
+ ```cmake
vcpkg_configure_cmake(
SOURCE_PATH ${SOURCE_PATH}
PREFER_NINJA
@@ -72,8 +89,10 @@ title: Windows 版编译说明
-DENABLE_OPENSSL:BOOL=ON
)
```
+
然后进行编译:
- ```
+
+ ```sh
.\vcpkg\vcpkg.exe install --triplet=x64-windows-static libsrtp
```
@@ -82,6 +101,7 @@ title: Windows 版编译说明
从开始菜单中打开 vs2015/2017/2019 的开发者命令行模式, 默认未找到基于 `powershell` 的 x64 位版本, 可先使用 `cmd` 版本, 然后执行 `powershell` 切换到 `powershell`.
1. 编译 ZLMediaKit
+
```powershell
mkdir build
cd build
@@ -103,11 +123,13 @@ title: Windows 版编译说明
```
编译 64 位程序在链接 `openssl` 时还需要链接 `Crypt32.lib` 和 `ws2_32.lib`, 正常在执行 `cmake .. @CMAKE_OPTIONS` 时有类似输出:
+
```
found library:C:/work/develop/vcpkg/installed/x64-windows-static/lib/libssl.lib;C:/work/develop/vcpkg/installed/x64-windows-static/lib/libcrypto.lib;Crypt32.lib;ws2_32.lib,ENABLE_OPENSSL defined
```
如果没有 `Crypt32.lib;ws2_32.lib`, 可手动修改 `CMakeLists.txt` 进行解决(可搜索 `OPENSSL_LIBRARIES` 找到对应位置).
+
```cmake
list(APPEND LINK_LIB_LIST ${OPENSSL_LIBRARIES} Crypt32.lib ws2_32.lib)
```
diff --git a/src/zh/guide/install/install_zlmediakit_using_vcpkg.md b/src/zh/guide/install/install_zlmediakit_using_vcpkg.md
index 3261be2..8ee50a8 100644
--- a/src/zh/guide/install/install_zlmediakit_using_vcpkg.md
+++ b/src/zh/guide/install/install_zlmediakit_using_vcpkg.md
@@ -3,15 +3,16 @@ title: vcpkg方式安装zlmediakit
---
# 简介
-vcpkg是一个跨平台的sdk包管理工具,类似于linux下的yum/apt,macOS下的homebrew;它同时支持linux/macOS/windows等多个平台,是c/c++开发者解决依赖的利器。
-目前zlmediakit已经于2023-08-08完成vcpkg平台的上线,用户可以通过vcpkg便捷安装zlmediakit c sdk以及MediaServer可执行程序,解决各种编译依赖相关的苦恼。
-zlmediakit上架vcpkg得到了[@JackBoosY](https://github.com/JackBoosY)大量的支持,在此表示由衷的感谢!
+vcpkg 是一个跨平台的 sdk 包管理工具,类似于 linux 下的 yum/apt,macOS 下的 homebrew;它同时支持 linux/macOS/windows 等多个平台,是 c/c++开发者解决依赖的利器。
+目前 zlmediakit 已经于 2023-08-08 完成 vcpkg 平台的上线,用户可以通过 vcpkg 便捷安装 zlmediakit c sdk 以及 MediaServer 可执行程序,解决各种编译依赖相关的苦恼。
+zlmediakit 上架 vcpkg 得到了[@JackBoosY](https://github.com/JackBoosY)大量的支持,在此表示由衷的感谢!
# 安装指导
-## 1、安装vcpkg
-以linux平台为例:
+## 1、安装 vcpkg
+
+以 linux 平台为例:
```bash
# 下载vcpkg工具
@@ -22,9 +23,7 @@ git clone https://github.com/microsoft/vcpkg
> 不同平台具体参考[官方文档](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md)
-
-
-## 2、安装zlmediakit
+## 2、安装 zlmediakit
- 先安装依赖
@@ -32,54 +31,44 @@ git clone https://github.com/microsoft/vcpkg
sudo apt-get install pkg-config
```
-
-
-- 默认方式安装zlmediakit
+- 默认方式安装 zlmediakit
```bash
# 默认开启特性: [core,mp4,openssl,webrtc]
./vcpkg/vcpkg install zlmediakit
```
-
-
-- 安装全部特性zlmediakit(包括webrtc datachannel)
+- 安装全部特性 zlmediakit(包括 webrtc datachannel)
```bash
./vcpkg/vcpkg install zlmediakit\[core,mp4,openssl,webrtc,sctp\]
```
-
-
-- 最小安装zlmediakit
+- 最小安装 zlmediakit
```bash
./vcpkg/vcpkg install zlmediakit\[core\]
```
-
-
-- 卸载zlmediakit
+- 卸载 zlmediakit
```bash
./vcpkg/vcpkg remove zlmediakit
```
- 安装路径
-![](/images/install_zlmediakit_using_vcpkg_1.png)
-> MediaServer进程依赖的config.ini, default.pem, www等相关文件可以从源码拷贝过来
+ ![](/images/install_zlmediakit_using_vcpkg_1.png)
+ > MediaServer 进程依赖的 config.ini, default.pem, www 等相关文件可以从源码拷贝过来
## 3、安装不同版本
-- 查看vcpkg支持哪些平台
+- 查看 vcpkg 支持哪些平台
```bash
./vcpkg/vcpkg help triplet
```
-
-
-- 以linux为例
+- 以 linux 为例
```bash
./vcpkg/vcpkg help triplet | grep linux
@@ -105,7 +94,7 @@ git clone https://github.com/microsoft/vcpkg
riscv32-linux-release
```
-- 安装动态库版本zlmediakit
+- 安装动态库版本 zlmediakit
```bash
# 先卸载zlmediakit
@@ -113,6 +102,5 @@ git clone https://github.com/microsoft/vcpkg
# 然后安装动态库版本
./vcpkg/vcpkg install zlmediakit\[core,mp4,openssl,webrtc,sctp\]:x64-linux-dynamic
```
-![install_zlmediakit_using_vcpkg_2](/images/install_zlmediakit_using_vcpkg_2.png)
-
+ ![install_zlmediakit_using_vcpkg_2](/images/install_zlmediakit_using_vcpkg_2.png)
diff --git a/src/zh/guide/install/start.md b/src/zh/guide/install/start.md
index 0f59f60..2c43045 100644
--- a/src/zh/guide/install/start.md
+++ b/src/zh/guide/install/start.md
@@ -2,56 +2,51 @@
title: 快速开始
order: 1
---
-## 1、获取代码
-
-**请不要使用github 下载zip包的方式下载源码**,务必使用git克隆ZLMediaKit的代码,因为ZLMediaKit依赖于第三方代码,zip包不会下载第三方依赖源码,你可以这样操作:
- ```bash
- #国内用户推荐从同步镜像网站gitee下载
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- #千万不要忘记执行这句命令
- git submodule update --init
- ```
+## 1、获取代码
+**请不要使用 github 下载 zip 包的方式下载源码**,务必使用 git 克隆 ZLMediaKit 的代码,因为 ZLMediaKit 依赖于第三方代码,zip 包不会下载第三方依赖源码,你可以这样操作:
+```bash
+#国内用户推荐从同步镜像网站gitee下载
+git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+cd ZLMediaKit
+#千万不要忘记执行这句命令
+git submodule update --init
+```
## 2、强烈推荐
-如果你是位新手,强烈建议使用ubuntu16或更新版本编译ZLMediaKit,macOS是次选推荐平台,最不推荐的是centos6.*或windows平台。
-
-zlmediakit已上架vcpkg,便捷安装请参考[vcpkg安装zlmediakit](install_zlmediakit_using_vcpkg.md)
-
+如果你是位新手,强烈建议使用 ubuntu16 或更新版本编译 ZLMediaKit,macOS 是次选推荐平台,最不推荐的是 centos6.\*或 windows 平台。
+zlmediakit 已上架 vcpkg,便捷安装请参考[vcpkg 安装 zlmediakit](install_zlmediakit_using_vcpkg.md)
## 3、编译器
### 3.1、编译器版本要求
-ZLMediaKit采用了C++11的语法和库,要求编译器支持完整的C++11标准,亦即:
-
-- linux上要求gcc 版本 >= 4.8(4.7应该也能支持)
-- macOS上clang >= ???(我也不知道,估计大部分不会遇到这个问题)
-- windows 上visual stuido >= 2015(vs2013某些版本也能编译通过,如果怕麻烦建议直接vs2017)
-
+ZLMediaKit 采用了 C++11 的语法和库,要求编译器支持完整的 C++11 标准,亦即:
+- linux 上要求 gcc 版本 >= 4.8(4.7 应该也能支持)
+- macOS 上 clang >= ???(我也不知道,估计大部分不会遇到这个问题)
+- windows 上 visual stuido >= 2015(vs2013 某些版本也能编译通过,如果怕麻烦建议直接 vs2017)
### 3.2、安装编译器
-- 如果你是debian系操作系统(包括ubuntu系用户),一般自带的gcc版本够新,你可以这样安装gcc编译器:
+- 如果你是 debian 系操作系统(包括 ubuntu 系用户),一般自带的 gcc 版本够新,你可以这样安装 gcc 编译器:
```bash
sudo apt-get install build-essential
```
-- 如果你是centos7或以上用户,你可以这样安装gcc编译器:
+- 如果你是 centos7 或以上用户,你可以这样安装 gcc 编译器:
```cpp
sudo yum -y install gcc
sudo yum -y install gcc-c++
```
-- 如果你是centos6.*用户,你可以这样安装gcc编译器:
+- 如果你是 centos6.\*用户,你可以这样安装 gcc 编译器:
```bash
sudo yum install centos-release-scl -y
@@ -60,29 +55,27 @@ ZLMediaKit采用了C++11的语法和库,要求编译器支持完整的C++11标
scl enable devtoolset-4 bash
```
-- 如果你是macOS用户,你直接安装xcode即可。
-
-- 如果你是windows用户,推荐安装vs2017或以上。
-
+- 如果你是 macOS 用户,你直接安装 xcode 即可。
+- 如果你是 windows 用户,推荐安装 vs2017 或以上。
## 4、cmake
-ZLMediaKit采用cmake来构建项目,通过cmake才能生成Makefile(或Xcode/VS工程),所以必须先安装cmake才能完成后续步骤。
+ZLMediaKit 采用 cmake 来构建项目,通过 cmake 才能生成 Makefile(或 Xcode/VS 工程),所以必须先安装 cmake 才能完成后续步骤。
-- 如果你是debian系操作系统(包括ubuntu系用户),一般自带的cmake版本够新,你可以这样安装cmake
+- 如果你是 debian 系操作系统(包括 ubuntu 系用户),一般自带的 cmake 版本够新,你可以这样安装 cmake
```bash
sudo apt-get install cmake
```
-- 如果你是centos7或以上用户,你也许可以这样安装cmake:
+- 如果你是 centos7 或以上用户,你也许可以这样安装 cmake:
```cpp
sudo yum -y install cmake
```
-- 如果你是centos6.*用户,那么你需要下载新版本的cmake源码然后编译安装cmake
+- 如果你是 centos6.\*用户,那么你需要下载新版本的 cmake 源码然后编译安装 cmake
```bash
wget https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3.tar.gz
@@ -93,56 +86,45 @@ ZLMediaKit采用cmake来构建项目,通过cmake才能生成Makefile(或Xcode/
sudo make install
```
-- 如果你是macOS用户,你可以这样安装cmake:
+- 如果你是 macOS 用户,你可以这样安装 cmake:
```bash
brew install cmake
```
-
-- 如果你是windows用户,并且vs版本为2017及以上,你不用单独安装cmake,否则你需要安装cmake-gui:
+- 如果你是 windows 用户,并且 vs 版本为 2017 及以上,你不用单独安装 cmake,否则你需要安装 cmake-gui:
```bash
#安装win64版本cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win64-x64.zip
-
+
#安装win32版本cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win32-x86.zip
```
-
-
## 5、依赖库
### 5.1、依赖库列表
-ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构建ZLMediaKit时,cmake能查找系统路径中的这些库,并根据安装情况选择是否开启相关特性,你可以选择安装这些依赖并启用相关特性:
+ZLMediaKit 可选依赖一些第三方库,这些库都不是必选的;在构建 ZLMediaKit 时,cmake 能查找系统路径中的这些库,并根据安装情况选择是否开启相关特性,你可以选择安装这些依赖并启用相关特性:
- openssl
- - flash player在播放rtmp时,采用的是复杂握手模式,如果不安装该库,flash player将播放不了zlmediakit 提供的rtmp url.
-
- - 同时ZLMediaKit的https/rtsps/webrtc相关功能需要使用openssl才能开启。
-
-
+ - flash player 在播放 rtmp 时,采用的是复杂握手模式,如果不安装该库,flash player 将播放不了 zlmediakit 提供的 rtmp url.
+ - 同时 ZLMediaKit 的 https/rtsps/webrtc 相关功能需要使用 openssl 才能开启。
- ffmpeg
- zlmediakit可以通过fork ffmpeg进程的方式实现多种协议的拉流,编译时不需要安装FFmpeg。
-
-
+ zlmediakit 可以通过 fork ffmpeg 进程的方式实现多种协议的拉流,编译时不需要安装 FFmpeg。
- sdl、avcodec、avutil
- 这3个库供ZLMediaKit的test_player测试程序使用,你通常不需要安装这3个库。
-
-
-
+ 这 3 个库供 ZLMediaKit 的 test_player 测试程序使用,你通常不需要安装这 3 个库。
### 5.2、安装依赖库
-- Debian系(包括ubuntu)系统下安装依赖的方法:
+- Debian 系(包括 ubuntu)系统下安装依赖的方法:
```sh
#除了openssl,其他其实都可以不安装
@@ -152,24 +134,24 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
sudo apt-get install libavutil-dev
sudo apt-get install ffmpeg
```
-- centos6.*的用户可以参考该[文章](https://blog.51cto.com/mengix/2452395)
-- macOS/centos下安装依赖库:
+- centos6.\*的用户可以参考该[文章](https://blog.51cto.com/mengix/2452395)
- 基本安装方式跟Debian系安装差不多,安装命令分别改成brew / yum即可。但是有些库名字与Debian系不太一样,请自行查找相关资料。
+- macOS/centos 下安装依赖库:
-- windows下安装依赖库
+ 基本安装方式跟 Debian 系安装差不多,安装命令分别改成 brew / yum 即可。但是有些库名字与 Debian 系不太一样,请自行查找相关资料。
- - 安装openssl
+- windows 下安装依赖库
- 请从[网站](http://slproweb.com/products/Win32OpenSSL.html)中下载。
+ - 安装 openssl
+ 请从[网站](http://slproweb.com/products/Win32OpenSSL.html)中下载。
## 6、构建和编译项目
-由于开启webrtc相关功能比较复杂,默认是不开启编译的,如果你对zlmediakit的webrtc功能比较感兴趣,可以参考[这里](../protocol/webrtc/webrtc_compilation_and_use.md)
+由于开启 webrtc 相关功能比较复杂,默认是不开启编译的,如果你对 zlmediakit 的 webrtc 功能比较感兴趣,可以参考[这里](../protocol/webrtc/webrtc_compilation_and_use.md)
-- 在linux或macOS系统下,你应该这样操作:
+- 在 linux 或 macOS 系统下,你应该这样操作:
```bash
cd ZLMediaKit
@@ -180,11 +162,9 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
make -j4
```
+- 在 windows 系统下
-
-- 在windows系统下
-
- - 如果你是vs2017或以上,可以在vs菜单栏中直接打开项目文件夹:
+ - 如果你是 vs2017 或以上,可以在 vs 菜单栏中直接打开项目文件夹:
```bash
[文件] -> [打开] -> [文件夹] -> [选择ZLMediaKit代码根目录并打开]
@@ -192,23 +172,19 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
![image](/images/vs_code_zh.png)
- - 如果你是vs2017以下版本,你需要使用cmake-gui生成vs工程然后编译:
+ - 如果你是 vs2017 以下版本,你需要使用 cmake-gui 生成 vs 工程然后编译:
- ```sh
- 1 进入ZLMediaKit目录执行 git submodule update --init 以下载ZLToolKit的代码
- 2 使用cmake-gui打开工程并生成vs工程文件.
- 3 找到工程文件(ZLMediaKit.sln),双击用vs2017打开.
- 4 选择编译Release 版本.
+ 1 进入 ZLMediaKit 目录执行 git submodule update --init 以下载 ZLToolKit 的代码
+ 2 使用 cmake-gui 打开工程并生成 vs 工程文件.
+ 3 找到工程文件(ZLMediaKit.sln),双击用 vs2017 打开.
+ 4 选择编译 Release 版本.
5 找到目标文件并运行测试用例.
- ```
- - 同时,Windows编译也可以参考[这里](compilation_instructions_for_windows_version.md)
-
-- 如果你要编译Android版本,你可以自己在Android Studio中打开Android目录。
+ - 同时,Windows 编译也可以参考[这里](compilation_instructions_for_windows_version.md)
+- 如果你要编译 Android 版本,你可以自己在 Android Studio 中打开 Android 目录。
-
-- 如果你要编译ios版本,可以生成xcode工程然后编译c api的静态库;另外,你可以参考此[文档](https://www.jianshu.com/p/44c21296add5)
+- 如果你要编译 ios 版本,可以生成 xcode 工程然后编译 c api 的静态库;另外,你可以参考此[文档](https://www.jianshu.com/p/44c21296add5)
```sh
cd ZLMediaKit
@@ -218,20 +194,16 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
```
-
-
## 7、运行
-ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径在release目录下,这些目标文件主要分为:
+ZLMediaKit 工程主要生成 3 种二进制目标文件,他们的生成的路径在 release 目录下,这些目标文件主要分为:
-- MediaServer进程
+- MediaServer 进程
- 这是ZLMediaKit作为服务器的主进程,该进程可以在免去开发的情况下直接作为测试流媒体服务器使用,如果你需要更复杂的业务逻辑,可以通过[Web HOOK](../guide/media_server/web_hook_api.
+ 这是 ZLMediaKit 作为服务器的主进程,该进程可以在免去开发的情况下直接作为测试流媒体服务器使用,如果你需要更复杂的业务逻辑,可以通过[Web HOOK](../guide/media_server/web_hook_api.
md)和[RESTful API](../media_server/restful_api.md)实现,同时你可以通过[配置文件](../media_server/config_file.md)控制其参数。
-
-
- - 在linux下启动:
+ - 在 linux 下启动:
```sh
cd ZLMediaKit/release/linux/Debug
@@ -241,15 +213,11 @@ ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径
./MediaServer -d &
```
-
-
- - 在macos下启动:
+ - 在 macos 下启动:
- 目标文件目录在ZLMediaKit/mac/Debug,其他操作完全一致。
+ 目标文件目录在 ZLMediaKit/mac/Debug,其他操作完全一致。
-
-
- - 在window下启动:
+ - 在 window 下启动:
```sh
1 进入ZLMediaKit/release/windows/Debug目录
@@ -257,42 +225,35 @@ ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径
3 你也可以在cmd或powershell中启动,通过MediaServer -h了解启动参数
```
-
-
-- c api 的SDK
+- c api 的 SDK
- ZLMediaKit也提供c的api二次开发sdk库,头文件在`ZLMediaKit/api/include`,库文件为:
+ ZLMediaKit 也提供 c 的 api 二次开发 sdk 库,头文件在`ZLMediaKit/api/include`,库文件为:
- - linux下:
+ - linux 下:
```sh
ZLMediaKit/release/linux/Debug/libmk_api.so
```
- - macOS下:
+ - macOS 下:
```sh
ZLMediaKit/release/linux/mac/libmk_api.dylib
```
- - windows下:
+ - windows 下:
```sh
ZLMediaKit/release/windows/Debug/mk_api.dll
ZLMediaKit/release/windows/Debug/mk_api.lib
```
- SDK头文件有详细的注释,一般足够二次开发使用。
-
-
+ SDK 头文件有详细的注释,一般足够二次开发使用。
- 以`test_`开头的测试程序
相关代码在`ZLMediaKit/tests`目录下,你可以对照代码启动测试进程。
-
-
## 8、测试
请参考[此文章](../media_server/push_test.md)完成推流播放测试
-
diff --git a/src/zh/guide/media_server/README.md b/src/zh/guide/media_server/README.md
index b5df788..64bb6c5 100644
--- a/src/zh/guide/media_server/README.md
+++ b/src/zh/guide/media_server/README.md
@@ -14,6 +14,3 @@ tag:
- [Playing URL Rules](play_url_rules.md)
- [Starting and Stopping the Server](start_server.md)
-
-
-
diff --git a/src/zh/guide/media_server/config_file.md b/src/zh/guide/media_server/config_file.md
index c4f5112..49c37b8 100644
--- a/src/zh/guide/media_server/config_file.md
+++ b/src/zh/guide/media_server/config_file.md
@@ -1,6 +1,7 @@
---
title: 配置文件详解
---
+
[配置文件范例以及注释](https://github.com/zlmediakit/ZLMediaKit/blob/master/conf/config.ini)
-也可以参考[MediaServer支持的HTTP-HOOK-API](web_hook_api.md)了解hook相关的配置
+也可以参考[MediaServer 支持的 HTTP-HOOK-API](web_hook_api.md)了解 hook 相关的配置
diff --git a/src/zh/guide/media_server/generate_ssl_self-signed_certificate_and_test.md b/src/zh/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
index 95fcaa0..73d088a 100644
--- a/src/zh/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
+++ b/src/zh/guide/media_server/generate_ssl_self-signed_certificate_and_test.md
@@ -1,16 +1,21 @@
---
title: 生成SSL自签名证书并测试
---
-# 1、创建私钥
+
+## 1、创建私钥
+
```bash
openssl genrsa -out server.key 2048
```
-# 2、 创建签名请求文件
+## 2、 创建签名请求文件
+
```bash
openssl req -new -key server.key -out server.csr
```
+
注意,需要输入域名(Common Name (e.g. server FQDN or YOUR name)):
+
```bash
Country Name (2 letter code) [AU]:cn
State or Province Name (full name) [Some-State]:gd
@@ -26,25 +31,30 @@ A challenge password []:
An optional company name []:zlm
```
-# 3、自签名,生成公钥(10年有效期)
+## 3、自签名,生成公钥(10 年有效期)
+
```bash
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
```
+
执行该命令会打印以下信息:
+
```bash
Signature ok
subject=/C=cn/ST=gd/L=sz/O=company/OU=section/CN=zlm.com/emailAddress=xiachu@qq.com
Getting Private key
```
-# 4、合并公钥私钥
+## 4、合并公钥私钥
+
```bash
cat server.crt server.key > ./ssl.pem
```
-# 5、加载证书
+## 5、加载证书
+
```bash
./MediaServer -s ./ssl.pem
```
-![图片.png](/images/generate_ssl_self-signed_certificate_and_test.webp)
+![图片.png](/images/generate_ssl_self-signed_certificate_and_test.webp)
diff --git a/src/zh/guide/media_server/how_to_enable_https_related_functions.md b/src/zh/guide/media_server/how_to_enable_https_related_functions.md
index b41b195..6b8fa13 100644
--- a/src/zh/guide/media_server/how_to_enable_https_related_functions.md
+++ b/src/zh/guide/media_server/how_to_enable_https_related_functions.md
@@ -2,13 +2,15 @@
title: 怎么开启https相关功能
---
-## 一、编译时开启openssl特性
-zlmediakit的https(另外还包括rtmps/rtsps/webrtc/wss)功能依赖openssl库,在编译zlmediakit时,应该先在系统默认环境安装openssl库,ubuntu下通过以下命令安装:
+## 一、编译时开启 openssl 特性
+
+zlmediakit 的 https(另外还包括 rtmps/rtsps/webrtc/wss)功能依赖 openssl 库,在编译 zlmediakit 时,应该先在系统默认环境安装 openssl 库,ubuntu 下通过以下命令安装:
+
```bash
sudo apt-get install libssl-dev
```
-如果您的系统默认openssl版本太老,可以选择自行编译安装openssl到自定义路径;此时,在编译zlmediakit时可以通过以下命令指定openssl自定义安装路径:
+如果您的系统默认 openssl 版本太老,可以选择自行编译安装 openssl 到自定义路径;此时,在编译 zlmediakit 时可以通过以下命令指定 openssl 自定义安装路径:
```bash
cd ZLMediaKit
@@ -19,7 +21,8 @@ make -j$(nproc)
```
## 二、创建证书
-- 如果你还没购买域名,可以使用[自签名证书](./generate_ssl_self-signed_certificate_and_test.md)或zlmediakit自带默认证书`default.pem`测试。
+
+- 如果你还没购买域名,可以使用[自签名证书](./generate_ssl_self-signed_certificate_and_test.md)或 zlmediakit 自带默认证书`default.pem`测试。
- **如果你已经购买域名,以阿里云为例,你可以选择为您的域名申请免费证书:**
@@ -33,21 +36,21 @@ make -j$(nproc)
![图片](/images/how_to_enable_https_related_functions_zh_3.png)
-## 三、下载证书并合并为zlmediakit支持的证书类型:
+## 三、下载证书并合并为 zlmediakit 支持的证书类型:
+
- **下载证书:**
![图片](/images/how_to_enable_https_related_functions_zh_4.png)
-- **选择下载nginx或其他方式都可(两者证书类型一样):**
+- **选择下载 nginx 或其他方式都可(两者证书类型一样):**
![图片](/images/how_to_enable_https_related_functions_zh_5.png)
- **解压下载压缩包后文件如下**:
-
+![图片](https://user-images.githubusercontent.com/11495632/191884186-3c09f0ed-0042-417c-a8dc-ad87c4c0c1ed.png =760x)
-
-- key后缀的文件是私钥,pem后缀的文件为公钥,两者可以使用文本编辑器打开,它们都是base64编码的字符串,两个字符串拼接在一起后就是zlmediakit支持的证书文件类型了:
+- key 后缀的文件是私钥,pem 后缀的文件为公钥,两者可以使用文本编辑器打开,它们都是 base64 编码的字符串,两个字符串拼接在一起后就是 zlmediakit 支持的证书文件类型了:
```bash
#进入文件夹
@@ -56,7 +59,7 @@ cd 8516590_test.zlmediakit.com_nginx
cat 8516590_test.zlmediakit.com.key 8516590_test.zlmediakit.com.pem > default.pem
```
-## 四、zlmediakit加载证书
+## 四、zlmediakit 加载证书
```bash
#进入zlmediakit编译后的二进制目录(不同平台路径有所不同)
@@ -71,11 +74,9 @@ cp ~/Downloads/8516590_test.zlmediakit.com_nginx/default.pem ./
![图片](/images/how_to_enable_https_related_functions_zh_6.png)
-
-
## 五、测试
-- 如果你的开发机的ip并不是证书绑定域名映射映射的ip,那么可以通过修改host文件来实现测试, 以linux/mac为例:
+- 如果你的开发机的 ip 并不是证书绑定域名映射映射的 ip,那么可以通过修改 host 文件来实现测试, 以 linux/mac 为例:
```bash
#打开host文件
@@ -85,7 +86,7 @@ sudo vi /etc/hosts
#修改后保存退出vi
```
-- **打开浏览器输入https地址测试:**
+- **打开浏览器输入 https 地址测试:**
![图片](/images/how_to_enable_https_related_functions_zh_7.png)
@@ -93,18 +94,10 @@ sudo vi /etc/hosts
![图片](/images/how_to_enable_https_related_functions_zh_8.png)
-
## 六、部署线上环境
-- 以上5步都走完了,验证通过,那么我们接下来可以部署线上环境;部署线上环境只需要把证书绑定的域名解析到您云主机的真实公网ip即可:
+- 以上 5 步都走完了,验证通过,那么我们接下来可以部署线上环境;部署线上环境只需要把证书绑定的域名解析到您云主机的真实公网 ip 即可:
![图片](/images/how_to_enable_https_related_functions_zh_9.png)
![图片](/images/how_to_enable_https_related_functions_zh_10.png)
-
-
-
-
-
-
-
diff --git a/src/zh/guide/media_server/on-demand_push_streaming.md b/src/zh/guide/media_server/on-demand_push_streaming.md
index 0283b5a..b598aee 100644
--- a/src/zh/guide/media_server/on-demand_push_streaming.md
+++ b/src/zh/guide/media_server/on-demand_push_streaming.md
@@ -2,5 +2,6 @@
title: 实现按需推流
---
-使用ZLMediaKit的MediaServer进程可以实现按需推流:
+使用 ZLMediaKit 的 MediaServer 进程可以实现按需推流:
+
![image](/images/on-demand_push_streaming_zh.png)
diff --git a/src/zh/guide/media_server/on-demand_streaming.md b/src/zh/guide/media_server/on-demand_streaming.md
index d7da88f..4c09459 100644
--- a/src/zh/guide/media_server/on-demand_streaming.md
+++ b/src/zh/guide/media_server/on-demand_streaming.md
@@ -1,7 +1,7 @@
---
title: 实现按需拉流
---
-使用ZLMediaKit的MediaServer进程可以实现按需拉流:
-![image](/images/on-demand_streaming_zh.png)
+使用 ZLMediaKit 的 MediaServer 进程可以实现按需拉流:
+![image](/images/on-demand_streaming_zh.png)
diff --git a/src/zh/guide/media_server/play_url_rules.md b/src/zh/guide/media_server/play_url_rules.md
index 4a7e941..46d5f02 100644
--- a/src/zh/guide/media_server/play_url_rules.md
+++ b/src/zh/guide/media_server/play_url_rules.md
@@ -3,53 +3,62 @@ title: 播放url规则
icon: circle-info
---
-## 1、url的组成部分
-以`rtsp://somedomain.com:554/live/0?token=abcdefg&field=value`为例,该url分为以下几个部分:
-- `协议(scheam)` : rtsp协议,默认端口554
-- `虚拟主机(vhost)` : somedomain.com,该字段既可以是域名也可以是ip,如果是ip则对应的虚拟主机为`__defaultVhost__`
+## 1、url 的组成部分
+
+以`rtsp://somedomain.com:554/live/0?token=abcdefg&field=value`为例,该 url 分为以下几个部分:
+
+- `协议(scheam)` : rtsp 协议,默认端口 554
+- `虚拟主机(vhost)` : somedomain.com,该字段既可以是域名也可以是 ip,如果是 ip 则对应的虚拟主机为`__defaultVhost__`
- `服务端口号(port)` : 554,如果不指定端口号,则使用协议默认端口号
- `应用名(app)` : live
- `流ID(streamid)` : 0
- `参数(args)` : token=abcdefg&field=value
-## 2、ZLMediaKit中的流媒体源
-在ZLMediaKit中,流媒体源是一种可以被用于直播转发、推流转发等功能的数据对象,在本项目中被称作为`MediaSource`,目前支持5种类型的流媒体源,分别是`RtspMediaSource`、`RtmpMediaSource`、`HlsMediaSource`、`TSMediaSource`、`FMP4MediaSource`。
+## 2、ZLMediaKit 中的流媒体源
+
+在 ZLMediaKit 中,流媒体源是一种可以被用于直播转发、推流转发等功能的数据对象,在本项目中被称作为`MediaSource`,目前支持 5 种类型的流媒体源,分别是`RtspMediaSource`、`RtmpMediaSource`、`HlsMediaSource`、`TSMediaSource`、`FMP4MediaSource`。
+
+定位一个流媒体源,主要通过 4 个元素(我们后续称其为 4 元组),分别是:
-定位一个流媒体源,主要通过4个元素(我们后续称其为4元组),分别是:
- `协议(scheam)`
- `虚拟主机(vhost)`
- `应用名(app)`
- `流ID(streamid) `
-`RtspMediaSource`支持 rtsp播放、rtsp推流、webrtc播放、webrtc推流。
+`RtspMediaSource`支持 rtsp 播放、rtsp 推流、webrtc 播放、webrtc 推流。
-`RtmpMediaSource`支持 rtmp推流/播放、http-flv播放、ws-flv播放。
+`RtmpMediaSource`支持 rtmp 推流/播放、http-flv 播放、ws-flv 播放。
-`HlsMediaSource`支持 hls播放。
+`HlsMediaSource`支持 hls 播放。
-`TSMediaSource` 支持 http-ts播放、ws-ts播放。
+`TSMediaSource` 支持 http-ts 播放、ws-ts 播放。
-`FMP4MediaSource` 支持 http-fmp4播放、ws-fmp4播放。
+`FMP4MediaSource` 支持 http-fmp4 播放、ws-fmp4 播放。
+## 3、流媒体源对应的播放 url
+
+假定有一个`RtspMediaSource`,它的 4 元组分别为 `rtsp(RtspMediaSource固定为rtsp)`、`somedomain.com`、`live`、`0`
+那么播放这个流媒体源的 url 对应为:
-## 3、流媒体源对应的播放url
-假定有一个`RtspMediaSource`,它的4元组分别为 `rtsp(RtspMediaSource固定为rtsp)`、`somedomain.com`、`live`、`0`
-那么播放这个流媒体源的url对应为:
- `rtsp://somedomain.com/live/0`
- `rtsps://somedomain.com/live/0`
- `rtsp://127.0.0.1/live/0?vhost=somedomain.com`
- `rtsps://127.0.0.1/live/0?vhost=somedomain.com`
-如果有一个`RtmpMediaSource`,它的4元组分别为 `rtmp(RtmpMediaSource固定为rtmp)`、`somedomain.com`、`live`、`0`
-那么播放这个流媒体源的url对应为:
+如果有一个`RtmpMediaSource`,它的 4 元组分别为 `rtmp(RtmpMediaSource固定为rtmp)`、`somedomain.com`、`live`、`0`
+那么播放这个流媒体源的 url 对应为:
+
- `rtmp://somedomain.com/live/0`
- `rtmps://somedomain.com/live/0`
- `rtmp://127.0.0.1/live/0?vhost=somedomain.com`
- `rtmps://127.0.0.1/live/0?vhost=somedomain.com`
-rtmp类型的流媒体源也支持`http-flv`、`websocket`直播,对应的url如下:
+rtmp 类型的流媒体源也支持`http-flv`、`websocket`直播,对应的 url 如下:
+
+::: warning 老代码 flv 直播后缀为.flv,新代码才改成了.live.flv
+
+:::
-**注意: 老代码flv直播后缀为.flv,新代码才改成了.live.flv**
- `http://somedomain.com/live/0.live.flv`
- `https://somedomain.com/live/0.live.flv`
- `http://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
@@ -59,20 +68,24 @@ rtmp类型的流媒体源也支持`http-flv`、`websocket`直播,对应的url
- `ws://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
- `wss://127.0.0.1/live/0.live.flv?vhost=somedomain.com`
-当然,ZLMediaKit一般会把rtsp、rtmp流媒体源互相转换,也会转换成hls/http-ts/ws-ts/http-fmp4/ws-fmp4,播放的url如下:
+当然,ZLMediaKit 一般会把 rtsp、rtmp 流媒体源互相转换,也会转换成 hls/http-ts/ws-ts/http-fmp4/ws-fmp4,播放的 url 如下:
+
- HLS(mpegts)
+
- `http://somedomain.com/live/0/hls.m3u8`
- `https://somedomain.com/live/0/hls.m3u8`
- `http://127.0.0.1/live/0/hls.m3u8?vhost=somedomain.com`
- `https://127.0.0.1/live/0/hls.m3u8?vhost=somedomain.com`
- HLS(fmp4)
+
- `http://somedomain.com/live/0/hls.fmp4.m3u8`
- `https://somedomain.com/live/0/hls.fmp4.m3u8`
- `http://127.0.0.1/live/0/hls.fmp4.m3u8?vhost=somedomain.com`
- `https://127.0.0.1/live/0/hls.fmp4.m3u8?vhost=somedomain.com`
-- HTTP-TS/WS-TS(后缀为.live.ts,目的是为了解决与hls的冲突)
+- HTTP-TS/WS-TS(后缀为.live.ts,目的是为了解决与 hls 的冲突)
+
- `http://somedomain.com/live/0.live.ts`
- `https://somedomain.com/live/0.live.ts`
- `http://127.0.0.1/live/0.live.ts?vhost=somedomain.com`
@@ -82,8 +95,7 @@ rtmp类型的流媒体源也支持`http-flv`、`websocket`直播,对应的url
- `ws://127.0.0.1/live/0.live.ts?vhost=somedomain.com`
- `wss://127.0.0.1/live/0.live.ts?vhost=somedomain.com`
-
-- HTTP-fMP4/WS-fMP4(后缀为.live.mp4,目的是为了解决与mp4点播的冲突)
+- HTTP-fMP4/WS-fMP4(后缀为.live.mp4,目的是为了解决与 mp4 点播的冲突)
- `http://somedomain.com/live/0.live.mp4`
- `https://somedomain.com/live/0.live.mp4`
- `http://127.0.0.1/live/0.live.mp4?vhost=somedomain.com`
@@ -93,39 +105,41 @@ rtmp类型的流媒体源也支持`http-flv`、`websocket`直播,对应的url
- `ws://127.0.0.1/live/0.live.mp4?vhost=somedomain.com`
- `wss://127.0.0.1/live/0.live.mp4?vhost=somedomain.com`
-一般而言,上述url在ZLMediaKit都有效,因为ZLMediaKit默认转换流媒体源。
-
-## 4、点播url
-ZLMediaKit的点播一般通过mp4文件来实现,推荐大家使用http mp4点播,这样是最简单,服务器也无需解复用mp4文件,当然ZLMediaKit目前也支持rtsp、rtmp、http-flv、websocket-flv的mp4点播,
-对应的url跟直播url类似,不在赘述,这里只介绍区别。
-- ZLMediaKit对点播限制应用名,默认为`record`
-- 假如一个mp4文件放置在http根目录record文件夹(`www/record`)下,他的相对路径为:`www/record/0.mp4`,那么点播url则为:
- - `rtsp://somedomain.com/record/0.mp4`
- - `rtmp://somedomain.com/record/0.mp4`
- - `http://somedomain.com/record/0.mp4`(这里是通用的http文件点播,服务器不用解复用文件)
- - `http://somedomain.com/record/0.mp4.live.flv`(这里是http-flv直播,不是http点播,服务器需要解复用文件)
- - `ws://somedomain.com/record/0.mp4.live.flv`
- - `http://somedomain.com/record/0.mp4.live.ts`(这里是http-ts直播,不是http点播,服务器需要解复用文件)
- - `ws://somedomain.com/record/0.mp4.live.ts`
- - `http://somedomain.com/record/0.mp4.live.mp4`(这里是http-fmp4直播,不是http点播,服务器需要解复用文件)
- - `ws://somedomain.com/record/0.mp4.live.mp4`
+一般而言,上述 url 在 ZLMediaKit 都有效,因为 ZLMediaKit 默认转换流媒体源。
+
+## 4、点播 url
+
+ZLMediaKit 的点播一般通过 mp4 文件来实现,推荐大家使用 http mp4 点播,这样是最简单,服务器也无需解复用 mp4 文件,当然 ZLMediaKit 目前也支持 rtsp、rtmp、http-flv、websocket-flv 的 mp4 点播,
+对应的 url 跟直播 url 类似,不在赘述,这里只介绍区别。
+
+- ZLMediaKit 对点播限制应用名,默认为`record`
+- 假如一个 mp4 文件放置在 http 根目录 record 文件夹(`www/record`)下,他的相对路径为:`www/record/0.mp4`,那么点播 url 则为:
+ - `rtsp://somedomain.com/record/0.mp4`
+ - `rtmp://somedomain.com/record/0.mp4`
+ - `http://somedomain.com/record/0.mp4`(这里是通用的 http 文件点播,服务器不用解复用文件)
+ - `http://somedomain.com/record/0.mp4.live.flv`(这里是 http-flv 直播,不是 http 点播,服务器需要解复用文件)
+ - `ws://somedomain.com/record/0.mp4.live.flv`
+ - `http://somedomain.com/record/0.mp4.live.ts`(这里是 http-ts 直播,不是 http 点播,服务器需要解复用文件)
+ - `ws://somedomain.com/record/0.mp4.live.ts`
+ - `http://somedomain.com/record/0.mp4.live.mp4`(这里是 http-fmp4 直播,不是 http 点播,服务器需要解复用文件)
+ - `ws://somedomain.com/record/0.mp4.live.mp4`
- 如果开启了虚拟主机,那么点播文件需要放置在 `www/somedomain.com/record/0.mp4`。
-## 5、webrtc推流/播放
-`webrtc`播放跟上述方式不太一样,webrtc协议本身不定义信令交互协议,用户自己去实现`sdp+icecandidate`交换逻辑,所以`webrtc`并没有一个标准的播放器,需要自己使用js或native sdk去实现播放。
+## 5、webrtc 推流/播放
-`zlmediakit`实现的`webrtc sdp+icecandidate`交换方式是`http post`方式,接口名为`/index/api/webrtc`, 该接口使用post content传递 `offer sdp`, 同时url query参数传递媒体源4元组中的`app` `steam_id`,由于http协议本身支持`vhost`,所以不需要另外指定`vhost`。 `webrtc`在`zlmediakit`中可以认为是rtsp协议的另外表现形式,他们推流、播放使用的数据源都相同,都是`RtspMediaSource`。
+`webrtc`播放跟上述方式不太一样,webrtc 协议本身不定义信令交互协议,用户自己去实现`sdp+icecandidate`交换逻辑,所以`webrtc`并没有一个标准的播放器,需要自己使用 js 或 native sdk 去实现播放。
-在webrtc推流时,交互`webrtc sdp+icecandidate`的http post接口类似为:`http://127.0.0.1/index/api/webrtc?app=live&stream=test&type=push`
+`zlmediakit`实现的`webrtc sdp+icecandidate`交换方式是`http post`方式,接口名为`/index/api/webrtc`, 该接口使用 post content 传递 `offer sdp`, 同时 url query 参数传递媒体源 4 元组中的`app` `steam_id`,由于 http 协议本身支持`vhost`,所以不需要另外指定`vhost`。 `webrtc`在`zlmediakit`中可以认为是 rtsp 协议的另外表现形式,他们推流、播放使用的数据源都相同,都是`RtspMediaSource`。
-在webrtc播放时,交互`webrtc sdp+icecandidate`的http post接口类似为:`http://127.0.0.1/index/api/webrtc?app=live&stream=test&type=play`。
+在 webrtc 推流时,交互`webrtc sdp+icecandidate`的 http post 接口类似为:`http://127.0.0.1/index/api/webrtc?app=live&stream=test&type=push`
-zlmeiakit工程自带webrtc测试播放/推流器,用户启动zlmediakit后,浏览器访问`http://127.0.0.1/webrtc/`就可以访问之。
+在 webrtc 播放时,交互`webrtc sdp+icecandidate`的 http post 接口类似为:`http://127.0.0.1/index/api/webrtc?app=live&stream=test&type=play`。
-另外,zlmediakit也支持使用webrtc播放mp4文件,http post接口类似为:`http://127.0.0.1/index/api/webrtc?app=record&stream=test.mp4&type=play`。
+zlmeiakit 工程自带 webrtc 测试播放/推流器,用户启动 zlmediakit 后,浏览器访问`http://127.0.0.1/webrtc/`就可以访问之。
-## 6、url参数
-ZLMediaKit会识别url中问号后面的字符串为url参数,其格式跟http一致,其中参数`vhost`是ZLMediaKit内置支持的参数,支持指定vhost。
-url参数主要用于播放、推流鉴权,在触发hook api时,会把这些参数提交给第三方业务服务器
+另外,zlmediakit 也支持使用 webrtc 播放 mp4 文件,http post 接口类似为:`http://127.0.0.1/index/api/webrtc?app=record&stream=test.mp4&type=play`。
+## 6、url 参数
+ZLMediaKit 会识别 url 中问号后面的字符串为 url 参数,其格式跟 http 一致,其中参数`vhost`是 ZLMediaKit 内置支持的参数,支持指定 vhost。
+url 参数主要用于播放、推流鉴权,在触发 hook api 时,会把这些参数提交给第三方业务服务器
diff --git a/src/zh/guide/media_server/playback_authentication.md b/src/zh/guide/media_server/playback_authentication.md
index ea36316..b15fdd1 100644
--- a/src/zh/guide/media_server/playback_authentication.md
+++ b/src/zh/guide/media_server/playback_authentication.md
@@ -1,6 +1,7 @@
---
title: 实现播放鉴权
---
-使用ZLMediaKit的MediaServer进程可以实现播放鉴权:
-![image](/images/playback_authentication_zh.png)
+使用 ZLMediaKit 的 MediaServer 进程可以实现播放鉴权:
+
+![image](/images/playback_authentication_zh.png)
diff --git a/src/zh/guide/media_server/push_authentication.md b/src/zh/guide/media_server/push_authentication.md
index 9ea7588..deb586a 100644
--- a/src/zh/guide/media_server/push_authentication.md
+++ b/src/zh/guide/media_server/push_authentication.md
@@ -1,7 +1,7 @@
---
title: 实现推流鉴权
---
-使用ZLMediaKit的MediaServer进程可以实现推流鉴权:
-![image](/images/push_authentication_zh.png)
+使用 ZLMediaKit 的 MediaServer 进程可以实现推流鉴权:
+![image](/images/push_authentication_zh.png)
diff --git a/src/zh/guide/media_server/push_test.md b/src/zh/guide/media_server/push_test.md
index e2371f6..6182917 100644
--- a/src/zh/guide/media_server/push_test.md
+++ b/src/zh/guide/media_server/push_test.md
@@ -1,10 +1,13 @@
---
title: 推流播放测试
---
+
## 推流测试
-ZLMediaKit支持rtsp/rtmp/rtp推流,一般通常使用obs/ffmpeg推流测试,其中FFmpeg推流命令支持以下:
-- 1、使用rtsp方式推流
+ZLMediaKit 支持 rtsp/rtmp/rtp 推流,一般通常使用 obs/ffmpeg 推流测试,其中 FFmpeg 推流命令支持以下:
+
+- 1、使用 rtsp 方式推流
+
```bash
# h264推流
ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
@@ -12,14 +15,16 @@ ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transpo
ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtsp -rtsp_transport tcp rtsp://127.0.0.1/live/test
```
-- 2、使用rtmp方式推流
+- 2、使用 rtmp 方式推流
+
```bash
#如果未安装FFmpeg,你也可以用obs推流
ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f flv rtmp://127.0.0.1/live/test
# RTMP标准不支持H265,但是国内有自行扩展的,如果你想让FFmpeg支持RTMP-H265,请按照此文章编译:https://github.com/ksvc/FFmpeg/wiki/hevcpush
```
-- 3、使用rtp方式推流
+- 3、使用 rtp 方式推流
+
```bash
# h264推流
ffmpeg -re -i "/path/to/test.mp4" -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
@@ -28,10 +33,12 @@ ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtp_mpegts rtp://1
```
## 观察日志
+
如果推流成功,会打印这种日志:
![image](/images/push_test.png)
日志中相关字符串分别代表:
+
```bash
2020-04-10 12:51:52.331 I | regist rtsp __defaultVhost__ rtp 206442D7
^ ^ ^ ^
@@ -39,6 +46,5 @@ ffmpeg -re -i "/path/to/test.mp4" -vcodec h265 -acodec aac -f rtp_mpegts rtp://1
```
## 播放地址
-请按照[播放url规则](./play_url_rules.md)来播放上述的推流。
-
+请按照[播放 url 规则](./play_url_rules.md)来播放上述的推流。
diff --git a/src/zh/guide/media_server/restful_api.md b/src/zh/guide/media_server/restful_api.md
index fa9589d..97fe3a4 100644
--- a/src/zh/guide/media_server/restful_api.md
+++ b/src/zh/guide/media_server/restful_api.md
@@ -2,16 +2,15 @@
title: RESTful 接口
---
-## 下载postman配置文件(可以在线测试restful api)
+## 下载 postman 配置文件(可以在线测试 restful api)
-[postman配置文件](https://github.com/xia-chu/ZLMediaKit/tree/master/postman)
+[postman 配置文件](https://github.com/xia-chu/ZLMediaKit/tree/master/postman)
-由于接口更新频繁,在观看本文档的同时,请大家再使用postman核对测试接口,同时本文档可能有些接口有遗漏,你也可以参考[代码](https://github.com/xia-chu/ZLMediaKit/blob/master/server/WebApi.cpp#L261)
+由于接口更新频繁,在观看本文档的同时,请大家再使用 postman 核对测试接口,同时本文档可能有些接口有遗漏,你也可以参考[代码](https://github.com/xia-chu/ZLMediaKit/blob/master/server/WebApi.cpp#L261)
+## API 预览
-## API预览
-
-MediaServer是ZLMediaKit的主进程,目前支持以下http api接口,这些接口全部支持GET/POST方式,
+MediaServer 是 ZLMediaKit 的主进程,目前支持以下 http api 接口,这些接口全部支持 GET/POST 方式,
```ini
"/index/api/addFFmpegSource",
@@ -50,25 +49,24 @@ MediaServer是ZLMediaKit的主进程,目前支持以下http api接口,这些
"/index/api/getMediaPlayerList"
```
-其中POST方式,参数既可以使用urlencoded方式也可以使用json方式。
-操作这些api一般需要提供secret参数以便鉴权,如果操作ip是127.0.0.1,那么可以无需鉴权。
-
+其中 POST 方式,参数既可以使用 urlencoded 方式也可以使用 json 方式。
+操作这些 api 一般需要提供 secret 参数以便鉴权,如果操作 ip 是 127.0.0.1,那么可以无需鉴权。
-## API返回结果约定
+## API 返回结果约定
-- HTTP层面统一返回200状态码,body统一为json。
-- body一般为以下样式:
+- HTTP 层面统一返回 200 状态码,body 统一为 json。
+- body 一般为以下样式:
```json
{
- "code" : -1,
- "msg" : "失败提示"
+ "code": -1,
+ "msg": "失败提示"
}
```
-- code值代表执行结果,目前包含以下类型:
+- code 值代表执行结果,目前包含以下类型:
-```c++
+```cpp
typedef enum {
Exception = -400,//代码抛异常
InvalidArgs = -300,//参数不合法
@@ -95,11 +93,11 @@ typedef enum {
- `code == 0`时代表完全成功,如果有数据返回,一般提供`data`字段返回数据。
-## API详解
+## API 详解
### 0、`/index/api/getApiList`
-- 功能:获取API列表
+- 功能:获取 API 列表
- 范例:[http://127.0.0.1/index/api/getApiList](http://127.0.0.1/index/api/getApiList)
@@ -107,1201 +105,1131 @@ typedef enum {
- 响应:
- ```json
- {
- "code": 0,
- "data": [
- "/index/",
- "/index/api/addFFmpegSource",
- "/index/api/addStreamProxy",
- "/index/api/addStreamPusherProxy",
- "/index/api/closeRtpServer",
- "/index/api/close_stream",
- "/index/api/delFFmpegSource",
- "/index/api/delStreamProxy",
- "/index/api/delStreamPusherProxy",
- "/index/api/downloadBin",
- "/index/api/getAllSession",
- "/index/api/getApiList",
- "/index/api/getMediaInfo",
- "/index/api/getMediaList",
- "/index/api/getMp4RecordFile",
- "/index/api/getRtpInfo",
- "/index/api/getServerConfig",
- "/index/api/getSnap",
- "/index/api/getStatistic",
- "/index/api/getThreadsLoad",
- "/index/api/getWorkThreadsLoad",
- "/index/api/isMediaOnline",
- "/index/api/isRecording",
- "/index/api/kick_session",
- "/index/api/kick_sessions",
- "/index/api/listRtpServer",
- "/index/api/openRtpServer",
- "/index/api/pauseRtpCheck",
- "/index/api/restartServer",
- "/index/api/resumeRtpCheck",
- "/index/api/setServerConfig",
- "/index/api/startRecord",
- "/index/api/startSendRtp",
- "/index/api/stopRecord",
- "/index/api/stopSendRtp",
- "/index/api/version",
- "/index/api/webrtc",
- "/index/hook/on_flow_report",
- "/index/hook/on_http_access",
- "/index/hook/on_play",
- "/index/hook/on_publish",
- "/index/hook/on_record_hls",
- "/index/hook/on_record_mp4",
- "/index/hook/on_rtsp_auth",
- "/index/hook/on_rtsp_realm",
- "/index/hook/on_server_started",
- "/index/hook/on_shell_login",
- "/index/hook/on_stream_changed",
- "/index/hook/on_stream_none_reader",
- "/index/hook/on_stream_not_found",
- "/index/hook/on_stream_not_found_ffmpeg"
- ]
- }
- ```
-
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ "/index/",
+ "/index/api/addFFmpegSource",
+ "/index/api/addStreamProxy",
+ "/index/api/addStreamPusherProxy",
+ "/index/api/closeRtpServer",
+ "/index/api/close_stream",
+ "/index/api/delFFmpegSource",
+ "/index/api/delStreamProxy",
+ "/index/api/delStreamPusherProxy",
+ "/index/api/downloadBin",
+ "/index/api/getAllSession",
+ "/index/api/getApiList",
+ "/index/api/getMediaInfo",
+ "/index/api/getMediaList",
+ "/index/api/getMp4RecordFile",
+ "/index/api/getRtpInfo",
+ "/index/api/getServerConfig",
+ "/index/api/getSnap",
+ "/index/api/getStatistic",
+ "/index/api/getThreadsLoad",
+ "/index/api/getWorkThreadsLoad",
+ "/index/api/isMediaOnline",
+ "/index/api/isRecording",
+ "/index/api/kick_session",
+ "/index/api/kick_sessions",
+ "/index/api/listRtpServer",
+ "/index/api/openRtpServer",
+ "/index/api/pauseRtpCheck",
+ "/index/api/restartServer",
+ "/index/api/resumeRtpCheck",
+ "/index/api/setServerConfig",
+ "/index/api/startRecord",
+ "/index/api/startSendRtp",
+ "/index/api/stopRecord",
+ "/index/api/stopSendRtp",
+ "/index/api/version",
+ "/index/api/webrtc",
+ "/index/hook/on_flow_report",
+ "/index/hook/on_http_access",
+ "/index/hook/on_play",
+ "/index/hook/on_publish",
+ "/index/hook/on_record_hls",
+ "/index/hook/on_record_mp4",
+ "/index/hook/on_rtsp_auth",
+ "/index/hook/on_rtsp_realm",
+ "/index/hook/on_server_started",
+ "/index/hook/on_shell_login",
+ "/index/hook/on_stream_changed",
+ "/index/hook/on_stream_none_reader",
+ "/index/hook/on_stream_not_found",
+ "/index/hook/on_stream_not_found_ffmpeg"
+ ]
+ }
+ ```
### 1、`/index/api/getThreadsLoad`
- - 功能:获取各epoll(或select)线程负载以及延时
+- 功能:获取各 epoll(或 select)线程负载以及延时
- - 范例:[http://127.0.0.1/index/api/getThreadsLoad](http://127.0.0.1/index/api/getThreadsLoad)
+- 范例:[http://127.0.0.1/index/api/getThreadsLoad](http://127.0.0.1/index/api/getThreadsLoad)
- - 参数:无
+- 参数:无
- - 响应:
+- 响应:
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "delay" : 0, # 该线程延时
- "load" : 0 # 该线程负载,0 ~ 100
- },
- {
- "delay" : 0,
- "load" : 0
- }
- ]
- }
- ```
-
-
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "delay" : 0, # 该线程延时
+ "load" : 0 # 该线程负载,0 ~ 100
+ },
+ {
+ "delay" : 0,
+ "load" : 0
+ }
+ ]
+ }
+ ```
### 2、`/index/api/getWorkThreadsLoad`
- - 功能:获取各后台epoll(或select)线程负载以及延时
+- 功能:获取各后台 epoll(或 select)线程负载以及延时
- - 范例:[http://127.0.0.1/index/api/getWorkThreadsLoad](http://127.0.0.1/index/api/getWorkThreadsLoad)
+- 范例:[http://127.0.0.1/index/api/getWorkThreadsLoad](http://127.0.0.1/index/api/getWorkThreadsLoad)
- - 参数:无
+- 参数:无
- - 响应:
+- 响应:
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "delay" : 0, # 该线程延时
- "load" : 0 # 该线程负载,0 ~ 100
- },
- {
- "delay" : 0,
- "load" : 0
- }
- ]
- }
- ```
-
-
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "delay" : 0, # 该线程延时
+ "load" : 0 # 该线程负载,0 ~ 100
+ },
+ {
+ "delay" : 0,
+ "load" : 0
+ }
+ ]
+ }
+ ```
### 3、`/index/api/getServerConfig`
- - 功能:获取服务器配置
+- 功能:获取服务器配置
- - 范例:[http://127.0.0.1/index/api/getServerConfig](http://127.0.0.1/index/api/getServerConfig)
+- 范例:[http://127.0.0.1/index/api/getServerConfig](http://127.0.0.1/index/api/getServerConfig)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
- - 响应:
-
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "api.apiDebug" : "1",
- "api.secret" : "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
- "ffmpeg.bin" : "/usr/local/bin/ffmpeg",
- "ffmpeg.cmd" : "%s -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s",
- "ffmpeg.log" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/ffmpeg/ffmpeg.log",
- "general.enableVhost" : "1",
- "general.flowThreshold" : "1024",
- "general.maxStreamWaitMS" : "5000",
- "general.streamNoneReaderDelayMS" : "5000",
- "hls.fileBufSize" : "65536",
- "hls.filePath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "hls.segDur" : "3",
- "hls.segNum" : "3",
- "hook.access_file_except_hls" : "1",
- "hook.admin_params" : "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc",
- "hook.enable" : "1",
- "hook.on_flow_report" : "https://127.0.0.1/index/hook/on_flow_report",
- "hook.on_http_access" : "https://127.0.0.1/index/hook/on_http_access",
- "hook.on_play" : "https://127.0.0.1/index/hook/on_play",
- "hook.on_publish" : "https://127.0.0.1/index/hook/on_publish",
- "hook.on_record_mp4" : "https://127.0.0.1/index/hook/on_record_mp4",
- "hook.on_rtsp_auth" : "https://127.0.0.1/index/hook/on_rtsp_auth",
- "hook.on_rtsp_realm" : "https://127.0.0.1/index/hook/on_rtsp_realm",
- "hook.on_shell_login" : "https://127.0.0.1/index/hook/on_shell_login",
- "hook.on_stream_changed" : "https://127.0.0.1/index/hook/on_stream_changed",
- "hook.on_stream_none_reader" : "https://127.0.0.1/index/hook/on_stream_none_reader",
- "hook.on_stream_not_found" : "https://127.0.0.1/index/hook/on_stream_not_found",
- "hook.timeoutSec" : "10",
- "http.charSet" : "utf-8",
- "http.keepAliveSecond" : "100",
- "http.maxReqCount" : "100",
- "http.maxReqSize" : "4096",
- "http.notFound" : "404 Not Found您访问的资源不存在!
ZLMediaKit-4.0",
- "http.port" : "80",
- "http.rootPath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "http.sendBufSize" : "65536",
- "http.sslport" : "443",
- "multicast.addrMax" : "239.255.255.255",
- "multicast.addrMin" : "239.0.0.0",
- "multicast.udpTTL" : "64",
- "record.appName" : "record",
- "record.filePath" : "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
- "record.fileSecond" : "3600",
- "record.sampleMS" : "100",
- "rtmp.handshakeSecond" : "15",
- "rtmp.keepAliveSecond" : "15",
- "rtmp.modifyStamp" : "1",
- "rtmp.port" : "1935",
- "rtp.audioMtuSize" : "600",
- "rtp.clearCount" : "10",
- "rtp.cycleMS" : "46800000",
- "rtp.maxRtpCount" : "50",
- "rtp.videoMtuSize" : "1400",
- "rtsp.authBasic" : "0",
- "rtsp.handshakeSecond" : "15",
- "rtsp.keepAliveSecond" : "15",
- "rtsp.port" : "554",
- "rtsp.sslport" : "322",
- "shell.maxReqSize" : "1024",
- "shell.port" : "9000"
- }
- ]
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code": 0,
+ "data": [
+ {
+ "api.apiDebug": "1",
+ "api.secret": "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
+ "ffmpeg.bin": "/usr/local/bin/ffmpeg",
+ "ffmpeg.cmd": "%s -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s",
+ "ffmpeg.log": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/ffmpeg/ffmpeg.log",
+ "general.enableVhost": "1",
+ "general.flowThreshold": "1024",
+ "general.maxStreamWaitMS": "5000",
+ "general.streamNoneReaderDelayMS": "5000",
+ "hls.fileBufSize": "65536",
+ "hls.filePath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "hls.segDur": "3",
+ "hls.segNum": "3",
+ "hook.access_file_except_hls": "1",
+ "hook.admin_params": "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc",
+ "hook.enable": "1",
+ "hook.on_flow_report": "https://127.0.0.1/index/hook/on_flow_report",
+ "hook.on_http_access": "https://127.0.0.1/index/hook/on_http_access",
+ "hook.on_play": "https://127.0.0.1/index/hook/on_play",
+ "hook.on_publish": "https://127.0.0.1/index/hook/on_publish",
+ "hook.on_record_mp4": "https://127.0.0.1/index/hook/on_record_mp4",
+ "hook.on_rtsp_auth": "https://127.0.0.1/index/hook/on_rtsp_auth",
+ "hook.on_rtsp_realm": "https://127.0.0.1/index/hook/on_rtsp_realm",
+ "hook.on_shell_login": "https://127.0.0.1/index/hook/on_shell_login",
+ "hook.on_stream_changed": "https://127.0.0.1/index/hook/on_stream_changed",
+ "hook.on_stream_none_reader": "https://127.0.0.1/index/hook/on_stream_none_reader",
+ "hook.on_stream_not_found": "https://127.0.0.1/index/hook/on_stream_not_found",
+ "hook.timeoutSec": "10",
+ "http.charSet": "utf-8",
+ "http.keepAliveSecond": "100",
+ "http.maxReqCount": "100",
+ "http.maxReqSize": "4096",
+ "http.notFound": "404 Not Found您访问的资源不存在!
ZLMediaKit-4.0",
+ "http.port": "80",
+ "http.rootPath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "http.sendBufSize": "65536",
+ "http.sslport": "443",
+ "multicast.addrMax": "239.255.255.255",
+ "multicast.addrMin": "239.0.0.0",
+ "multicast.udpTTL": "64",
+ "record.appName": "record",
+ "record.filePath": "/Users/xzl/git/ZLMediaKit/cmake-build-debug/bin/httpRoot",
+ "record.fileSecond": "3600",
+ "record.sampleMS": "100",
+ "rtmp.handshakeSecond": "15",
+ "rtmp.keepAliveSecond": "15",
+ "rtmp.modifyStamp": "1",
+ "rtmp.port": "1935",
+ "rtp.audioMtuSize": "600",
+ "rtp.clearCount": "10",
+ "rtp.cycleMS": "46800000",
+ "rtp.maxRtpCount": "50",
+ "rtp.videoMtuSize": "1400",
+ "rtsp.authBasic": "0",
+ "rtsp.handshakeSecond": "15",
+ "rtsp.keepAliveSecond": "15",
+ "rtsp.port": "554",
+ "rtsp.sslport": "322",
+ "shell.maxReqSize": "1024",
+ "shell.port": "9000"
+ }
+ ]
+ }
+ ```
### 4、`/index/api/setServerConfig`
- - 功能:设置服务器配置
-
- - 范例:[http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0(例如关闭http api调试)](http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0)
-
- - 参数:
+- 功能:设置服务器配置
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
+- 范例:[http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0(例如关闭 http api 调试)](http://127.0.0.1/index/api/setServerConfig?api.apiDebug=0)
- - 响应:
+- 参数:
- ```json
- {
- "changed" : 0, # 配置项变更个数
- "code" : 0 # 0代表成功
- }
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+- 响应:
+ ```json
+ {
+ "changed" : 0, # 配置项变更个数
+ "code" : 0 # 0代表成功
+ }
+ ```
### 5、`/index/api/restartServer`
- - 功能:重启服务器,只有Daemon方式才能重启,否则是直接关闭!
-
- - 范例:[http://127.0.0.1/index/api/restartServer](http://127.0.0.1/index/api/restartServer)
+- 功能:重启服务器,只有 Daemon 方式才能重启,否则是直接关闭!
- - 参数:
+- 范例:[http://127.0.0.1/index/api/restartServer](http://127.0.0.1/index/api/restartServer)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
-
- - 响应:
-
- ```json
- {
- "code" : 0,
- "msg" : "服务器将在一秒后自动重启"
- }
- ```
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+- 响应:
+ ```json
+ {
+ "code": 0,
+ "msg": "服务器将在一秒后自动重启"
+ }
+ ```
### 6、`/index/api/getMediaList`
- - 功能:获取流列表,可选筛选参数
+- 功能:获取流列表,可选筛选参数
- - 范例:[http://127.0.0.1/index/api/getMediaList](http://127.0.0.1/index/api/getMediaList)
+- 范例:[http://127.0.0.1/index/api/getMediaList](http://127.0.0.1/index/api/getMediaList)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | N | 筛选协议,例如 rtsp或rtmp |
- | vhost | N | 筛选虚拟主机,例如`__defaultVhost__` |
- | app | N | 筛选应用名,例如 live |
- | stream | N | 筛选流id,例如 test |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :----------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | N | 筛选协议,例如 rtsp 或 rtmp |
+ | vhost | N | 筛选虚拟主机,例如`__defaultVhost__` |
+ | app | N | 筛选应用名,例如 live |
+ | stream | N | 筛选流 id,例如 test |
- - 响应:
+- 响应:
- ```json
+ ```json
+ {
+ "code" : 0,
+ "data" : [
{
- "code" : 0,
- "data" : [
- {
- "app" : "live", # 应用名
- "readerCount" : 0, # 本协议观看人数
- "totalReaderCount" : 0, # 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
- "schema" : "rtsp", # 协议
- "stream" : "obs", # 流id
- "originSock": { # 客户端和服务器网络信息,可能为null类型
- "identifier": "140241931428384",
- "local_ip": "127.0.0.1",
- "local_port": 1935,
- "peer_ip": "127.0.0.1",
- "peer_port": 50097
- },
- "originType": 1, # 产生源类型,包括 unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7
- "originTypeStr": "MediaOriginType::rtmp_push",
- "originUrl": "rtmp://127.0.0.1:1935/live/hks2", #产生源的url
- "createStamp": 1602205811, #GMT unix系统时间戳,单位秒
- "aliveSecond": 100, #存活时间,单位秒
- "bytesSpeed": 12345, #数据产生速度,单位byte/s
- "tracks" : [ # 音视频轨道
- {
- "channels" : 1, # 音频通道数
- "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # 编码类型名称
- "codec_type" : 1, # Video = 0, Audio = 1
- "ready" : true, # 轨道是否准备就绪
- "frames" : 1119, #累计接收帧数
- "sample_bit" : 16, # 音频采样位数
- "sample_rate" : 8000 # 音频采样率
- },
- {
- "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # 编码类型名称
- "codec_type" : 0, # Video = 0, Audio = 1
- "fps" : 59, # 视频fps
- "frames" : 1119, #累计接收帧数,不包含sei/aud/sps/pps等不能解码的帧
- "gop_interval_ms" : 1993, #gop间隔时间,单位毫秒
- "gop_size" : 60, #gop大小,单位帧数
- "key_frames" : 21, #累计接收关键帧数
- "height" : 720, # 视频高
- "ready" : true, # 轨道是否准备就绪
- "width" : 1280 # 视频宽
- }
- ],
- "vhost" : "__defaultVhost__" # 虚拟主机名
- }
- ]
- }
- ```
-
-
+ "app" : "live", # 应用名
+ "readerCount" : 0, # 本协议观看人数
+ "totalReaderCount" : 0, # 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
+ "schema" : "rtsp", # 协议
+ "stream" : "obs", # 流id
+ "originSock": { # 客户端和服务器网络信息,可能为null类型
+ "identifier": "140241931428384",
+ "local_ip": "127.0.0.1",
+ "local_port": 1935,
+ "peer_ip": "127.0.0.1",
+ "peer_port": 50097
+ },
+ "originType": 1, # 产生源类型,包括 unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7
+ "originTypeStr": "MediaOriginType::rtmp_push",
+ "originUrl": "rtmp://127.0.0.1:1935/live/hks2", #产生源的url
+ "createStamp": 1602205811, #GMT unix系统时间戳,单位秒
+ "aliveSecond": 100, #存活时间,单位秒
+ "bytesSpeed": 12345, #数据产生速度,单位byte/s
+ "tracks" : [ # 音视频轨道
+ {
+ "channels" : 1, # 音频通道数
+ "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecAAC", # 编码类型名称
+ "codec_type" : 1, # Video = 0, Audio = 1
+ "ready" : true, # 轨道是否准备就绪
+ "frames" : 1119, #累计接收帧数
+ "sample_bit" : 16, # 音频采样位数
+ "sample_rate" : 8000 # 音频采样率
+ },
+ {
+ "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecH264", # 编码类型名称
+ "codec_type" : 0, # Video = 0, Audio = 1
+ "fps" : 59, # 视频fps
+ "frames" : 1119, #累计接收帧数,不包含sei/aud/sps/pps等不能解码的帧
+ "gop_interval_ms" : 1993, #gop间隔时间,单位毫秒
+ "gop_size" : 60, #gop大小,单位帧数
+ "key_frames" : 21, #累计接收关键帧数
+ "height" : 720, # 视频高
+ "ready" : true, # 轨道是否准备就绪
+ "width" : 1280 # 视频宽
+ }
+ ],
+ "vhost" : "__defaultVhost__" # 虚拟主机名
+ }
+ ]
+ }
+ ```
-### 7、`/index/api/close_stream`(已过期,请使用close_streams接口替换)
+### 7、`/index/api/close_stream`(已过期,请使用 close_streams 接口替换)
- - 功能:关闭流(目前所有类型的流都支持关闭)
+- 功能:关闭流(目前所有类型的流都支持关闭)
- - 范例:[http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
+- 范例:[http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_stream?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | Y | 协议,例如 rtsp或rtmp |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 test |
- | force | N | 是否强制关闭(有人在观看是否还关闭) |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :--------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | Y | 协议,例如 rtsp 或 rtmp |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 test |
+ | force | N | 是否强制关闭(有人在观看是否还关闭) |
- - 响应:
+- 响应:
- ```json
- {
- "code" : 0,
- "result" : 0,# 0:成功,-1:关闭失败,-2:该流不存在
- "msg" : "success"
- }
- ```
+ ```json
+ {
+ "code" : 0,
+ "result" : 0,# 0:成功,-1:关闭失败,-2:该流不存在
+ "msg" : "success"
+ }
+ ```
### 8、`/index/api/close_streams`
- - 功能:关闭流(目前所有类型的流都支持关闭)
+- 功能:关闭流(目前所有类型的流都支持关闭)
- - 范例:[http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
+- 范例:[http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=`__defaultVhost__`&app=live&stream=0&force=1](http://127.0.0.1/index/api/close_streams?schema=rtmp&vhost=__defaultVhost__&app=live&stream=0&force=1)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | N | 协议,例如 rtsp或rtmp |
- | vhost | N | 虚拟主机,例如`__defaultVhost__` |
- | app | N | 应用名,例如 live |
- | stream | N | 流id,例如 test |
- | force | N | 是否强制关闭(有人在观看是否还关闭) |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :--------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | N | 协议,例如 rtsp 或 rtmp |
+ | vhost | N | 虚拟主机,例如`__defaultVhost__` |
+ | app | N | 应用名,例如 live |
+ | stream | N | 流 id,例如 test |
+ | force | N | 是否强制关闭(有人在观看是否还关闭) |
- - 响应:
+- 响应:
- ```json
- {
- "code" : 0,
- "count_hit" : 1, # 筛选命中的流个数
- "count_closed" : 1 # 被关闭的流个数,可能小于count_hit
- }
- ```
+ ```json
+ {
+ "code" : 0,
+ "count_hit" : 1, # 筛选命中的流个数
+ "count_closed" : 1 # 被关闭的流个数,可能小于count_hit
+ }
+ ```
### 9、`/index/api/getAllSession`
- - 功能:获取所有TcpSession列表(获取所有tcp客户端相关信息)
-
- - 范例:[http://127.0.0.1/index/api/getAllSession](http://127.0.0.1/index/api/getAllSession)
+- 功能:获取所有 TcpSession 列表(获取所有 tcp 客户端相关信息)
- - 参数:
+- 范例:[http://127.0.0.1/index/api/getAllSession](http://127.0.0.1/index/api/getAllSession)
- | 参数 | 是否必选 | 释意 |
- | :--------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | local_port | N | 筛选本机端口,例如筛选rtsp链接:554 |
- | peer_ip | N | 筛选客户端ip |
+- 参数:
- - 响应:
+ | 参数 | 是否必选 | 释意 |
+ | :--------: | :------: | :-----------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | local_port | N | 筛选本机端口,例如筛选 rtsp 链接:554 |
+ | peer_ip | N | 筛选客户端 ip |
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "id" : "140614477848784",
- "local_ip" : "127.0.0.1",
- "local_port" : 80,
- "peer_ip" : "127.0.0.1",
- "peer_port" : 51136,
- "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
- },
- {
- "id" : "140614443300192",
- "local_ip" : "127.0.0.1",
- "local_port" : 80,
- "peer_ip" : "127.0.0.1",
- "peer_port" : 51135,
- "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
- },
- {
- "id" : "140614440178720", # 该tcp链接唯一id
- "local_ip" : "127.0.0.1", # 本机网卡ip
- "local_port" : 1935, # 本机端口号 (这是个rtmp播放器或推流器)
- "peer_ip" : "127.0.0.1", # 客户端ip
- "peer_port" : 51130, # 客户端端口号
- "typeid" : "N8mediakit11RtmpSessionE" # 客户端TCPSession typeid
- }
- ]
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "id" : "140614477848784",
+ "local_ip" : "127.0.0.1",
+ "local_port" : 80,
+ "peer_ip" : "127.0.0.1",
+ "peer_port" : 51136,
+ "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
+ },
+ {
+ "id" : "140614443300192",
+ "local_ip" : "127.0.0.1",
+ "local_port" : 80,
+ "peer_ip" : "127.0.0.1",
+ "peer_port" : 51135,
+ "typeid" : "16WebSocketSessionI11EchoSessionN8mediakit11HttpSessionEE"
+ },
+ {
+ "id" : "140614440178720", # 该tcp链接唯一id
+ "local_ip" : "127.0.0.1", # 本机网卡ip
+ "local_port" : 1935, # 本机端口号 (这是个rtmp播放器或推流器)
+ "peer_ip" : "127.0.0.1", # 客户端ip
+ "peer_port" : 51130, # 客户端端口号
+ "typeid" : "N8mediakit11RtmpSessionE" # 客户端TCPSession typeid
+ }
+ ]
+ }
+ ```
### 10、`/index/api/kick_session`
- - 功能:断开tcp连接,比如说可以断开rtsp、rtmp播放器等
+- 功能:断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等
- - 范例:[http://127.0.0.1/index/api/kick_session?id=140614440178720](http://127.0.0.1/index/api/kick_session?id=140614440178720)
+- 范例:[http://127.0.0.1/index/api/kick_session?id=140614440178720](http://127.0.0.1/index/api/kick_session?id=140614440178720)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | Id | Y | 客户端唯一id,可以通过getAllSession接口获取 |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :--------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | Id | Y | 客户端唯一 id,可以通过 getAllSession 接口获取 |
- - 响应:
-
- ```json
- {
- "code" : 0,
- "msg" : "success"
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code": 0,
+ "msg": "success"
+ }
+ ```
### 11、`/index/api/kick_sessions`
- - 功能:断开tcp连接,比如说可以断开rtsp、rtmp播放器等
-
- - 范例:[http://127.0.0.1/index/api/kick_sessions?local_port=554](http://127.0.0.1/index/api/kick_sessions?local_port=554)
-
- - 参数:
+- 功能:断开 tcp 连接,比如说可以断开 rtsp、rtmp 播放器等
- | 参数 | 是否必选 | 释意 |
- | :--------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | local_port | N | 筛选本机端口,例如筛选rtsp链接:554 |
- | peer_ip | N | 筛选客户端ip |
+- 范例:[http://127.0.0.1/index/api/kick_sessions?local_port=554](http://127.0.0.1/index/api/kick_sessions?local_port=554)
- - 响应:
+- 参数:
- ```json
- {
- "code" : 0,
- "count_hit" : 1,# 筛选命中客户端个数
- "msg" : "success"
- }
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :--------: | :------: | :-----------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | local_port | N | 筛选本机端口,例如筛选 rtsp 链接:554 |
+ | peer_ip | N | 筛选客户端 ip |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "count_hit" : 1,# 筛选命中客户端个数
+ "msg" : "success"
+ }
+ ```
### 12、`/index/api/addStreamProxy`
- - 功能:动态添加rtsp/rtmp/hls/http-ts/http-flv拉流代理(只支持H264/H265/aac/G711/opus负载)
-
- - 范例:[http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2](http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2)
-
- - 参数:
-
- | 参数 | 参数类型 | 释意 | 是否必选 |
- | :--------------: | :------: | :----------------------------------------------------------: | :------: |
- | secret | `string` | api操作密钥(配置文件配置) | Y |
- | vhost | `string` | 添加的流的虚拟主机,例如`__defaultVhost__` | Y |
- | app | `string` | 添加的流的应用名,例如live | Y |
- | stream | `string` | 添加的流的id名,例如test | Y |
- | url | `string` | 拉流地址,例如rtmp://live.hkstv.hk.lxdns.com/live/hks2 | Y |
- | retry_count | `int` | 拉流重试次数,默认为-1无限重试 | N |
- | rtp_type | `int` | rtsp拉流时,拉流方式,0:tcp,1:udp,2:组播 | N |
- | timeout_sec | `int` | 拉流超时时间,单位秒,float类型 | N |
- | `enable_hls` | `bool` | 是否转换成hls-mpegts协议 | N |
- | `enable_hls_fmp4` | `bool` | 是否转换成hls-fmp4协议 | N |
- | `enable_mp4` | `bool` | 是否允许mp4录制 | N |
- | `enable_rtsp` | `bool` | 是否转rtsp协议 | N |
- | `enable_rtmp` | `bool` | 是否转rtmp/flv协议 | N |
- | `enable_ts` | `bool` | 是否转http-ts/ws-ts协议 | N |
- | `enable_fmp4` | `bool` | 是否转http-fmp4/ws-fmp4协议 | N |
- | `hls_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `rtsp_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `rtmp_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `ts_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `fmp4_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `enable_audio` | `bool` | 转协议时是否开启音频 | N |
- | `add_mute_audio` | `bool` | 转协议时,无音频是否添加静音aac音频 | N |
- | `mp4_save_path` | `string` | mp4录制文件保存根目录,置空使用默认 | N |
- | `mp4_max_second` | `int` | mp4录制切片大小,单位秒 | N |
- | `mp4_as_player` | `bool` | MP4录制是否当作观看者参与播放人数计数 | N |
- | `hls_save_path` | `string` | hls文件保存保存根目录,置空使用默认 | N |
- | `modify_stamp` | `int` | 该流是否开启时间戳覆盖(0:绝对时间戳/1:系统时间戳/2:相对时间戳) | N |
- | `auto_close` | `bool` | 无人观看是否自动关闭流(不触发无人观看hook) | N |
-
- - 响应:
-
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "__defaultVhost__/proxy/0" # 流的唯一标识
- }
- }
- ```
+- 功能:动态添加 rtsp/rtmp/hls/http-ts/http-flv 拉流代理(只支持 H264/H265/aac/G711/opus 负载)
+
+- 范例:[http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2](http://127.0.0.1/index/api/addStreamProxy?vhost=__defaultVhost__&app=proxy&stream=0&url=rtmp://live.hkstv.hk.lxdns.com/live/hks2)
+
+- 参数:
+
+ | 参数 | 参数类型 | 释意 | 是否必选 |
+ | :---------------: | :------: | :------------------------------------------------------------: | :------: |
+ | secret | `string` | api 操作密钥(配置文件配置) | Y |
+ | vhost | `string` | 添加的流的虚拟主机,例如`__defaultVhost__` | Y |
+ | app | `string` | 添加的流的应用名,例如 live | Y |
+ | stream | `string` | 添加的流的 id 名,例如 test | Y |
+ | url | `string` | 拉流地址,例如 rtmp://live.hkstv.hk.lxdns.com/live/hks2 | Y |
+ | retry_count | `int` | 拉流重试次数,默认为-1 无限重试 | N |
+ | rtp_type | `int` | rtsp 拉流时,拉流方式,0:tcp,1:udp,2:组播 | N |
+ | timeout_sec | `int` | 拉流超时时间,单位秒,float 类型 | N |
+ | `enable_hls` | `bool` | 是否转换成 hls-mpegts 协议 | N |
+ | `enable_hls_fmp4` | `bool` | 是否转换成 hls-fmp4 协议 | N |
+ | `enable_mp4` | `bool` | 是否允许 mp4 录制 | N |
+ | `enable_rtsp` | `bool` | 是否转 rtsp 协议 | N |
+ | `enable_rtmp` | `bool` | 是否转 rtmp/flv 协议 | N |
+ | `enable_ts` | `bool` | 是否转 http-ts/ws-ts 协议 | N |
+ | `enable_fmp4` | `bool` | 是否转 http-fmp4/ws-fmp4 协议 | N |
+ | `hls_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `rtsp_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `rtmp_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `ts_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `fmp4_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `enable_audio` | `bool` | 转协议时是否开启音频 | N |
+ | `add_mute_audio` | `bool` | 转协议时,无音频是否添加静音 aac 音频 | N |
+ | `mp4_save_path` | `string` | mp4 录制文件保存根目录,置空使用默认 | N |
+ | `mp4_max_second` | `int` | mp4 录制切片大小,单位秒 | N |
+ | `mp4_as_player` | `bool` | MP4 录制是否当作观看者参与播放人数计数 | N |
+ | `hls_save_path` | `string` | hls 文件保存保存根目录,置空使用默认 | N |
+ | `modify_stamp` | `int` | 该流是否开启时间戳覆盖(0:绝对时间戳/1:系统时间戳/2:相对时间戳) | N |
+ | `auto_close` | `bool` | 无人观看是否自动关闭流(不触发无人观看 hook) | N |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "__defaultVhost__/proxy/0" # 流的唯一标识
+ }
+ }
+ ```
### 13、`/index/api/delStreamProxy(流注册成功后,也可以使用close_streams接口替代)`
- - 功能:关闭拉流代理
+- 功能:关闭拉流代理
- - 范例:[http://127.0.0.1/index/api/delStreamProxy?key=`__defaultVhost__`/proxy/0](http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0)
+- 范例:[http://127.0.0.1/index/api/delStreamProxy?key=`__defaultVhost__`/proxy/0](http://127.0.0.1/index/api/delStreamProxy?key=__defaultVhost__/proxy/0)
- - 参数:
-
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | key | Y | addStreamProxy接口返回的key |
-
- - 响应:
-
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # 成功与否
- }
- }
- ```
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :---------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | key | Y | addStreamProxy 接口返回的 key |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # 成功与否
+ }
+ }
+ ```
### 14、`/index/api/addFFmpegSource`
- - 功能:通过fork FFmpeg进程的方式拉流代理,支持任意协议
-
- - 范例:[http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd](http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd)
+- 功能:通过 fork FFmpeg 进程的方式拉流代理,支持任意协议
- - 参数:
+- 范例:[http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd](http://127.0.0.1/index/api/addFFmpegSource?src_url=http://live.hkstv.hk.lxdns.com/live/hks2/playlist.m3u8&dst_url=rtmp://127.0.0.1/live/hks2&timeout_ms=10000&ffmpeg_cmd_key=ffmpeg.cmd)
- | 参数 | 是否必选 | 释意 |
- | :--------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | src_url | Y | FFmpeg拉流地址,支持任意协议或格式(只要FFmpeg支持即可) |
- | dst_url | Y | FFmpeg rtmp推流地址,一般都是推给自己,例如rtmp://127.0.0.1/live/stream_form_ffmpeg |
- | timeout_ms | Y | FFmpeg推流成功超时时间 |
- | enable_hls | Y | 是否开启hls录制 |
- | enable_mp4 | Y | 是否开启mp4录制 |
- | ffmpeg_cmd_key | N | 配置文件中FFmpeg命令参数模板key(非内容),置空则采用默认模板:`ffmpeg.cmd` |
+- 参数:
- - 响应:
-
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "5f748d2ef9712e4b2f6f970c1d44d93a" # 唯一key
- }
- }
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :------------: | :------: | :-----------------------------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | src_url | Y | FFmpeg 拉流地址,支持任意协议或格式(只要 FFmpeg 支持即可) |
+ | dst_url | Y | FFmpeg rtmp 推流地址,一般都是推给自己,例如 rtmp://127.0.0.1/live/stream_form_ffmpeg |
+ | timeout_ms | Y | FFmpeg 推流成功超时时间 |
+ | enable_hls | Y | 是否开启 hls 录制 |
+ | enable_mp4 | Y | 是否开启 mp4 录制 |
+ | ffmpeg_cmd_key | N | 配置文件中 FFmpeg 命令参数模板 key(非内容),置空则采用默认模板:`ffmpeg.cmd` |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "5f748d2ef9712e4b2f6f970c1d44d93a" # 唯一key
+ }
+ }
+ ```
### 15、`/index/api/delFFmpegSource(流注册成功后,也可以使用close_streams接口替代)`
- - 功能:关闭ffmpeg拉流代理
-
- - 范例:[http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a](http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a)
-
- - 参数:
+- 功能:关闭 ffmpeg 拉流代理
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | key | Y | addFFmpegSource接口返回的key |
+- 范例:[http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a](http://127.0.0.1/index/api/delFFmpegSource?key=5f748d2ef9712e4b2f6f970c1d44d93a)
+- 参数:
- - 响应:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :----------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | key | Y | addFFmpegSource 接口返回的 key |
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # 成功与否
- }
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # 成功与否
+ }
+ }
+ ```
### 16、`/index/api/isMediaOnline(已过期,请使用getMediaList接口替代)`
- - 功能:判断直播流是否在线
-
- - 范例:[http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs)
+- 功能:判断直播流是否在线
- - 参数:
+- 范例:[http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isMediaOnline?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | Y | 协议,例如 rtsp或rtmp |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 obs |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | Y | 协议,例如 rtsp 或 rtmp |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 obs |
- - 响应:
-
- ```json
- {
- "code" : 0,
- "online" : true # 是否在线
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code" : 0,
+ "online" : true # 是否在线
+ }
+ ```
### 17、`/index/api/getMediaInfo(已过期,请使用getMediaList接口替代)`
- - 功能:获取流相关信息
-
- - 范例:[http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs)
+- 功能:获取流相关信息
- - 参数:
+- 范例:[http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/getMediaInfo?schema=rtsp&vhost=__defaultVhost__&app=live&stream=obs)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | Y | 协议,例如 rtsp或rtmp |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 obs |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | Y | 协议,例如 rtsp 或 rtmp |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 obs |
- - 响应:
+- 响应:
- ```json
- {
- "code" : 0,
- "online" : true, # 是否在线
- "readerCount" : 0, # 本协议观看人数
- "totalReaderCount" : 0, # 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
- "tracks" : [ # 轨道列表
- {
- "channels" : 1, # 音频通道数
- "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # 编码类型名称
- "codec_type" : 1, # Video = 0, Audio = 1
- "ready" : true, # 轨道是否准备就绪
- "sample_bit" : 16, # 音频采样位数
- "sample_rate" : 8000 # 音频采样率
- },
- {
- "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # 编码类型名称
- "codec_type" : 0, # Video = 0, Audio = 1
- "fps" : 59, # 视频fps
- "height" : 720, # 视频高
- "ready" : true, # 轨道是否准备就绪
- "width" : 1280 # 视频宽
- }
- ]
- }
- ```
+ ```json
+ {
+ "code" : 0,
+ "online" : true, # 是否在线
+ "readerCount" : 0, # 本协议观看人数
+ "totalReaderCount" : 0, # 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
+ "tracks" : [ # 轨道列表
+ {
+ "channels" : 1, # 音频通道数
+ "codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecAAC", # 编码类型名称
+ "codec_type" : 1, # Video = 0, Audio = 1
+ "ready" : true, # 轨道是否准备就绪
+ "sample_bit" : 16, # 音频采样位数
+ "sample_rate" : 8000 # 音频采样率
+ },
+ {
+ "codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
+ "codec_id_name" : "CodecH264", # 编码类型名称
+ "codec_type" : 0, # Video = 0, Audio = 1
+ "fps" : 59, # 视频fps
+ "height" : 720, # 视频高
+ "ready" : true, # 轨道是否准备就绪
+ "width" : 1280 # 视频宽
+ }
+ ]
+ }
+ ```
### 18、`/index/api/getRtpInfo`
- - 功能:获取rtp代理时的某路ssrc rtp信息
-
- - 范例:[http://127.0.0.1/index/api/getRtpInfo?stream_id=1A2B3C4D](http://127.0.0.1/index/api/getRtpInfo?ssrc=1A2B3C4D)
+- 功能:获取 rtp 代理时的某路 ssrc rtp 信息
- - 参数:
+- 范例:[http://127.0.0.1/index/api/getRtpInfo?stream_id=1A2B3C4D](http://127.0.0.1/index/api/getRtpInfo?ssrc=1A2B3C4D)
- | 参数 | 是否必选 | 释意 |
- | :-------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | stream_id | Y | RTP的ssrc,16进制字符串或者是流的id(openRtpServer接口指定) |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :-------: | :------: | :-------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | stream_id | Y | RTP 的 ssrc,16 进制字符串或者是流的 id(openRtpServer 接口指定) |
- - 响应:
-
- ```json
- {
- "code" : 0,
- "exist" : true, # 是否存在
- "peer_ip" : "192.168.0.23", # 推流客户端ip
- "peer_port" : 54000 # 客户端端口号
- "local_ip" : "0.0.0.0", #本地监听的网卡ip
- "local_port" : 10000
- }
- ```
+- 响应:
-
+ ```json
+ {
+ "code" : 0,
+ "exist" : true, # 是否存在
+ "peer_ip" : "192.168.0.23", # 推流客户端ip
+ "peer_port" : 54000 # 客户端端口号
+ "local_ip" : "0.0.0.0", #本地监听的网卡ip
+ "local_port" : 10000
+ }
+ ```
### 19、`/index/api/getMp4RecordFile`
- - 功能:搜索文件系统,获取流对应的录像文件列表或日期文件夹列表
+- 功能:搜索文件系统,获取流对应的录像文件列表或日期文件夹列表
- - 范例:[http://127.0.0.1/index/api/getMp4RecordFile?vhost=`__defaultVhost__`&app=live&stream=ss&period=2020-01](http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01)
+- 范例:[http://127.0.0.1/index/api/getMp4RecordFile?vhost=`__defaultVhost__`&app=live&stream=ss&period=2020-01](http://127.0.0.1/index/api/getMp4RecordFile?vhost=__defaultVhost__&app=live&stream=ss&period=2020-01)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | vhost | Y | 流的虚拟主机名 |
- | app | Y | 流的应用名 |
- | stream | Y | 流的ID |
- | period | Y | 流的录像日期,格式为2020-02-01,如果不是完整的日期,那么是搜索录像文件夹列表,否则搜索对应日期下的mp4文件列表 |
- | customized_path| N | 自定义搜索路径,与startRecord方法中的customized_path一样,默认为配置文件的路径 |
+ | 参数 | 是否必选 | 释意 |
+ | :-------------: | :------: | :-------------------------------------------------------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | vhost | Y | 流的虚拟主机名 |
+ | app | Y | 流的应用名 |
+ | stream | Y | 流的 ID |
+ | period | Y | 流的录像日期,格式为 2020-02-01,如果不是完整的日期,那么是搜索录像文件夹列表,否则搜索对应日期下的 mp4 文件列表 |
+ | customized_path | N | 自定义搜索路径,与 startRecord 方法中的 customized_path 一样,默认为配置文件的路径 |
+- 响应:
- - 响应:
+ ```json
+ # 搜索文件夹列表(按照前缀匹配规则):period = 2020-01
+ {
+ "code" : 0,
+ "data" : {
+ "paths" : [ "2020-01-25", "2020-01-24" ],
+ "rootPath" : "/www/record/live/ss/"
+ }
+ }
- ```json
- # 搜索文件夹列表(按照前缀匹配规则):period = 2020-01
- {
- "code" : 0,
- "data" : {
- "paths" : [ "2020-01-25", "2020-01-24" ],
- "rootPath" : "/www/record/live/ss/"
- }
- }
-
- # 搜索mp4文件列表:period = 2020-01-24
- {
- "code" : 0,
- "data" : {
- "paths" : [
- "22-20-30.mp4",
- "22-13-12.mp4",
- "21-57-07.mp4",
- "21-19-18.mp4",
- "21-24-21.mp4",
- "21-15-10.mp4",
- "22-14-14.mp4"
- ],
- "rootPath" : "/www/live/ss/2020-01-24/"
- }
- }
-
- ```
+ # 搜索mp4文件列表:period = 2020-01-24
+ {
+ "code" : 0,
+ "data" : {
+ "paths" : [
+ "22-20-30.mp4",
+ "22-13-12.mp4",
+ "21-57-07.mp4",
+ "21-19-18.mp4",
+ "21-24-21.mp4",
+ "21-15-10.mp4",
+ "22-14-14.mp4"
+ ],
+ "rootPath" : "/www/live/ss/2020-01-24/"
+ }
+ }
-
+ ```
### 20、`/index/api/startRecord`
- - 功能:开始录制hls或MP4
-
- - 范例:[http://127.0.0.1/index/api/startRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/startRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- 功能:开始录制 hls 或 MP4
- - 参数:
+- 范例:[http://127.0.0.1/index/api/startRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/startRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
- | 参数 | 是否必选 | 释意 | 类型 |
- | :-------------: | :------: | :----------------------------------------------------------: | ------ |
- | secret | Y | api操作密钥(配置文件配置) | string |
- | type | Y | 0为hls,1为mp4 | 0/1 |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` | string |
- | app | Y | 应用名,例如 live | string |
- | stream | Y | 流id,例如 obs | string |
- | customized_path | N | 录像保存目录 | string |
- | max_second | N | mp4录像切片时间大小,单位秒,置0则采用配置项 | int |
+- 参数:
+ | 参数 | 是否必选 | 释意 | 类型 |
+ | :-------------: | :------: | :--------------------------------------------: | ------ |
+ | secret | Y | api 操作密钥(配置文件配置) | string |
+ | type | Y | 0 为 hls,1 为 mp4 | 0/1 |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` | string |
+ | app | Y | 应用名,例如 live | string |
+ | stream | Y | 流 id,例如 obs | string |
+ | customized_path | N | 录像保存目录 | string |
+ | max_second | N | mp4 录像切片时间大小,单位秒,置 0 则采用配置项 | int |
+- 响应:
- - 响应:
-
- ```json
- {
- "code" : 0,
- "result" : true # 成功与否
- }
- ```
-
-
+ ```json
+ {
+ "code" : 0,
+ "result" : true # 成功与否
+ }
+ ```
### 21、`/index/api/stopRecord`
- - 功能:停止录制流
+- 功能:停止录制流
- - 范例:[http://127.0.0.1/index/api/stopRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/stopRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- 范例:[http://127.0.0.1/index/api/stopRecord?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/stopRecord?type=1&vhost=__defaultVhost__&app=live&stream=obs)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | type | Y | 0为hls,1为mp4 |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 obs |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | type | Y | 0 为 hls,1 为 mp4 |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 obs |
+- 响应:
- - 响应:
-
- ```json
- {
- "code" : 0,
- "result" : true # 成功与否
- }
- ```
-
-
+ ```json
+ {
+ "code" : 0,
+ "result" : true # 成功与否
+ }
+ ```
### 22、`/index/api/isRecording`
- - 功能:获取流录制状态
+- 功能:获取流录制状态
- - 范例:[http://127.0.0.1/index/api/isRecording?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isRecording?type=1&vhost=__defaultVhost__&app=live&stream=obs)
+- 范例:[http://127.0.0.1/index/api/isRecording?type=1&vhost=`__defaultVhost__`&app=live&stream=obs](http://127.0.0.1/index/api/isRecording?type=1&vhost=__defaultVhost__&app=live&stream=obs)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | type | Y | 0为hls,1为mp4 |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 obs |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | type | Y | 0 为 hls,1 为 mp4 |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 obs |
+- 响应:
- - 响应:
-
- ```json
- {
- "code" : 0,
- "status" : true # false:未录制,true:正在录制
- }
- ```
-
+ ```json
+ {
+ "code" : 0,
+ "status" : true # false:未录制,true:正在录制
+ }
+ ```
### 23、`/index/api/getSnap`
- - 功能:获取截图或生成实时截图并返回
-
- - 范例:[http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30](http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30)
-
- - 参数:
+- 功能:获取截图或生成实时截图并返回
- | 参数 | 是否必选 | 释意 |
- | :---------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | url | Y | 需要截图的url,可以是本机的,也可以是远程主机的 |
- | timeout_sec | Y | 截图失败超时时间,防止FFmpeg一直等待截图 |
- | expire_sec | Y | 截图的过期时间,该时间内产生的截图都会作为缓存返回 |
+- 范例:[http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30](http://127.0.0.1/index/api/getSnap?url=rtmp://127.0.0.1/record/robot.mp4&timeout_sec=10&expire_sec=30)
+- 参数:
- - 响应:
-
- ```json
- jpeg格式的图片,可以在浏览器直接打开
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :---------: | :------: | :------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | url | Y | 需要截图的 url,可以是本机的,也可以是远程主机的 |
+ | timeout_sec | Y | 截图失败超时时间,防止 FFmpeg 一直等待截图 |
+ | expire_sec | Y | 截图的过期时间,该时间内产生的截图都会作为缓存返回 |
+- 响应:
+ ```json
+ jpeg格式的图片,可以在浏览器直接打开
+ ```
### 24、`/index/api/openRtpServer`
- - 功能:创建GB28181 RTP接收端口,如果该端口接收数据超时,则会自动被回收(不用调用closeRtpServer接口)
-
- - 范例:[http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test](http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test)
-
- - 参数:
+- 功能:创建 GB28181 RTP 接收端口,如果该端口接收数据超时,则会自动被回收(不用调用 closeRtpServer 接口)
- | 参数 | 是否必选 | 释意 |
- | :--------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | port | Y | 接收端口,0则为随机端口 |
- | tcp_mode | Y | 0 udp 模式,1 tcp 被动模式, 2 tcp 主动模式。 (兼容enable_tcp 为0/1) |
- | stream_id | Y | 该端口绑定的流ID,该端口只能创建这一个流(而不是根据ssrc创建多个) |
+- 范例:[http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test](http://127.0.0.1/index/api/openRtpServer?port=0&tcp_mode=1&stream_id=test)
+- 参数:
- - 响应:
-
- ```json
- {
- "code" : 0,
- "port" : 55463 #接收端口,方便获取随机端口号
- }
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :-------: | :------: | :-------------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | port | Y | 接收端口,0 则为随机端口 |
+ | tcp_mode | Y | 0 udp 模式,1 tcp 被动模式, 2 tcp 主动模式。 (兼容 enable_tcp 为 0/1) |
+ | stream_id | Y | 该端口绑定的流 ID,该端口只能创建这一个流(而不是根据 ssrc 创建多个) |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "port" : 55463 #接收端口,方便获取随机端口号
+ }
+ ```
### 25、`/index/api/closeRtpServer`
- - 功能:关闭GB28181 RTP接收端口
-
- - 范例:[http://127.0.0.1/index/api/closeRtpServer?stream_id=test](http://127.0.0.1/index/api/closeRtpServer?stream_id=test)
+- 功能:关闭 GB28181 RTP 接收端口
- - 参数:
+- 范例:[http://127.0.0.1/index/api/closeRtpServer?stream_id=test](http://127.0.0.1/index/api/closeRtpServer?stream_id=test)
- | 参数 | 是否必选 | 释意 |
- | :-------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | stream_id | Y | 调用openRtpServer接口时提供的流ID |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :-------: | :------: | :----------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | stream_id | Y | 调用 openRtpServer 接口时提供的流 ID |
- - 响应:
+- 响应:
- ```json
- {
- "code": 0,
- "hit": 1 #是否找到记录并关闭
- }
- ```
+ ```json
+ {
+ "code": 0,
+ "hit": 1 #是否找到记录并关闭
+ }
+ ```
### 26、`/index/api/listRtpServer`
- - 功能:获取openRtpServer接口创建的所有RTP服务器
-
- - 范例:[http://127.0.0.1/index/api/listRtpServer](http://127.0.0.1/index/api/listRtpServer)
+- 功能:获取 openRtpServer 接口创建的所有 RTP 服务器
- - 参数:
+- 范例:[http://127.0.0.1/index/api/listRtpServer](http://127.0.0.1/index/api/listRtpServer)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
- - 响应:
-
- ```json
- {
- "code" : 0,
- "data" : [
- {
- "port" : 52183, #绑定的端口号
- "stream_id" : "test" #绑定的流ID
- }
- ]
- }
- ```
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "data" : [
+ {
+ "port" : 52183, #绑定的端口号
+ "stream_id" : "test" #绑定的流ID
+ }
+ ]
+ }
+ ```
### 27、`/index/api/startSendRtp`
- - 功能:作为GB28181客户端,启动ps-rtp推流,支持rtp/udp方式;该接口支持rtsp/rtmp等协议转ps-rtp推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试。
- - 范例:[http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0](http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0)
-
- - 参数:
-
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | vhost | Y | 虚拟主机,例如__defaultVhost__ |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 test |
- | ssrc | Y | 推流的rtp的ssrc,指定不同的ssrc可以同时推流到多个服务器 |
- | dst_url | Y | 目标ip或域名 |
- | dst_port | Y | 目标端口 |
- | is_udp | Y | 是否为udp模式,否则为tcp模式 |
- | src_port | N | 使用的本机端口,为0或不传时默认为随机端口 |
- | pt | N | 发送时,rtp的pt(uint8_t),不传时默认为96 |
- | use_ps | N | 发送时,rtp的负载类型。为1时,负载为ps;为0时,为es;不传时默认为1 |
- | only_audio | N | 当use_ps 为0时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0 |
+- 功能:作为 GB28181 客户端,启动 ps-rtp 推流,支持 rtp/udp 方式;该接口支持 rtsp/rtmp 等协议转 ps-rtp 推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试。
+- 范例:[http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0](http://127.0.0.1/index/api/startSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1&dst_url=127.0.0.1&dst_port=10000&is_udp=0)
+
+- 参数:
+
+ | 参数 | 是否必选 | 释意 |
+ | :--------: | :------: | :---------------------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | vhost | Y | 虚拟主机,例如**defaultVhost** |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 test |
+ | ssrc | Y | 推流的 rtp 的 ssrc,指定不同的 ssrc 可以同时推流到多个服务器 |
+ | dst_url | Y | 目标 ip 或域名 |
+ | dst_port | Y | 目标端口 |
+ | is_udp | Y | 是否为 udp 模式,否则为 tcp 模式 |
+ | src_port | N | 使用的本机端口,为 0 或不传时默认为随机端口 |
+ | pt | N | 发送时,rtp 的 pt(uint8_t),不传时默认为 96 |
+ | use_ps | N | 发送时,rtp 的负载类型。为 1 时,负载为 ps;为 0 时,为 es;不传时默认为 1 |
+ | only_audio | N | 当 use_ps 为 0 时,有效。为 1 时,发送音频;为 0 时,发送视频;不传时默认为 0 |
-
-
-
- - 响应:
+- 响应:
- ```json
- {
- "code": 0, #成功
- "local_port": 57152 #使用的本地端口号
- }
- ```
+ ```json
+ {
+ "code": 0, #成功
+ "local_port": 57152 #使用的本地端口号
+ }
+ ```
#### 27.1 、`/index/api/startSendRtpPassive`
- - 功能:作为GB28181 Passive TCP服务器;该接口支持rtsp/rtmp等协议转ps-rtp被动推流。调用该接口,zlm会启动tcp服务器等待连接请求,连接建立后,zlm会关闭tcp服务器,然后源源不断的往客户端推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试(不停地建立tcp监听,超时后再关闭)。
- - 范例:[http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1](http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1)
-
- - 参数:
-
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | vhost | Y | 虚拟主机,例如__defaultVhost__ |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 test |
- | ssrc | Y | 推流的rtp的ssrc,指定不同的ssrc可以同时推流到多个服务器 |
- | src_port | N | 使用的本机端口,为0或不传时默认为随机端口 |
- | pt | N | 发送时,rtp的pt(uint8_t),不传时默认为96 |
- | use_ps | N | 发送时,rtp的负载类型。为1时,负载为ps;为0时,为es;不传时默认为1 |
- | only_audio | N | 当use_ps 为0时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0 |
+- 功能:作为 GB28181 Passive TCP 服务器;该接口支持 rtsp/rtmp 等协议转 ps-rtp 被动推流。调用该接口,zlm 会启动 tcp 服务器等待连接请求,连接建立后,zlm 会关闭 tcp 服务器,然后源源不断的往客户端推流。第一次推流失败会直接返回错误,成功一次后,后续失败也将无限重试(不停地建立 tcp 监听,超时后再关闭)。
+- 范例:[http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test&ssrc=1](http://127.0.0.1/index/api/startSendRtpPassive?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test&ssrc=1)
-
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :--------: | :------: | :---------------------------------------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | vhost | Y | 虚拟主机,例如**defaultVhost** |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 test |
+ | ssrc | Y | 推流的 rtp 的 ssrc,指定不同的 ssrc 可以同时推流到多个服务器 |
+ | src_port | N | 使用的本机端口,为 0 或不传时默认为随机端口 |
+ | pt | N | 发送时,rtp 的 pt(uint8_t),不传时默认为 96 |
+ | use_ps | N | 发送时,rtp 的负载类型。为 1 时,负载为 ps;为 0 时,为 es;不传时默认为 1 |
+ | only_audio | N | 当 use_ps 为 0 时,有效。为 1 时,发送音频;为 0 时,发送视频;不传时默认为 0 |
- - 响应:
-
- ```json
- {
- "code": 0, #成功
- "local_port": 57152 #使用的本地端口号
- }
- ```
+- 响应:
+ ```json
+ {
+ "code": 0, #成功
+ "local_port": 57152 #使用的本地端口号
+ }
+ ```
### 28、`/index/api/stopSendRtp`
- - 功能:停止GB28181 ps-rtp推流
- - 范例:[http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test](http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test)
-
- - 参数:
+- 功能:停止 GB28181 ps-rtp 推流
+- 范例:[http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=`__defaultVhost__`&app=live&stream=test](http://127.0.0.1/index/api/stopSendRtp?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=test)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | vhost | Y | 虚拟主机,例如__defaultVhost__ |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 test |
- | ssrc | N | 根据ssrc关停某路rtp推流,置空时关闭所有流 |
-
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :-------------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | vhost | Y | 虚拟主机,例如**defaultVhost** |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 test |
+ | ssrc | N | 根据 ssrc 关停某路 rtp 推流,置空时关闭所有流 |
- - 响应:
+- 响应:
- ```json
- {
- "code": 0 #成功
- }
- ```
+ ```json
+ {
+ "code": 0 #成功
+ }
+ ```
### 29、`/index/api/getStatistic`
- - 功能:获取主要对象个数统计,主要用于分析内存性能
- - 范例:[http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc](http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc)
-
- - 参数:
+- 功能:获取主要对象个数统计,主要用于分析内存性能
+- 范例:[http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc](http://127.0.0.1/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc)
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
+- 参数:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
- - 响应:
+- 响应:
- ```json
- {
+ ```json
+ {
"code": 0,
"data": {
- "Buffer": 2,
- "BufferLikeString": 1,
- "BufferList": 0,
- "BufferRaw": 1,
- "Frame": 0,
- "FrameImp": 0,
- "MediaSource": 0,
- "MultiMediaSourceMuxer": 0,
- "Socket": 66,
- "TcpClient": 0,
- "TcpServer": 64,
- "TcpSession": 1
- }
+ "Buffer": 2,
+ "BufferLikeString": 1,
+ "BufferList": 0,
+ "BufferRaw": 1,
+ "Frame": 0,
+ "FrameImp": 0,
+ "MediaSource": 0,
+ "MultiMediaSourceMuxer": 0,
+ "Socket": 66,
+ "TcpClient": 0,
+ "TcpServer": 64,
+ "TcpSession": 1
}
- ```
+ }
+ ```
### 30、`/index/api/addStreamPusherProxy`
- - 功能:添加rtsp/rtmp主动推流(把本服务器的直播流推送到其他服务器去)
-
- - 范例:[http://127.0.0.1/index/api/addStreamPusherProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2](http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2)
-
- - 参数:
+- 功能:添加 rtsp/rtmp 主动推流(把本服务器的直播流推送到其他服务器去)
- | 参数 | 是否必选 | 释意 |
- | :---------: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | vhost | Y | 添加的流的虚拟主机,例如`__defaultVhost__` |
- | schema | Y | 协议,例如 rtsp或rtmp |
- | app | Y | 添加的流的应用名,例如live |
- | stream | Y | 需要转推的流id |
- | dst_url | Y | 目标转推url,带参数需要自行url转义 |
- | retry_count | N | 转推失败重试次数,默认无限重试 |
- | rtp_type | N | rtsp推流时,推流方式,0:tcp,1:udp |
- | timeout_sec | N | 推流超时时间,单位秒,float类型 |
+- 范例:[http://127.0.0.1/index/api/addStreamPusherProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2](http://127.0.0.1/index/api/addStreamProxy?vhost=`__defaultVhost__`&app=proxy&stream=test&dst_url=rtmp://127.0.0.1/live/test2)
- - 响应:
+- 参数:
- ```json
- {
- "code" : 0,
- "data" : {
- "key" : "rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12" # 流的唯一标识
- }
- }
- ```
+ | 参数 | 是否必选 | 释意 |
+ | :---------: | :------: | :----------------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | vhost | Y | 添加的流的虚拟主机,例如`__defaultVhost__` |
+ | schema | Y | 协议,例如 rtsp 或 rtmp |
+ | app | Y | 添加的流的应用名,例如 live |
+ | stream | Y | 需要转推的流 id |
+ | dst_url | Y | 目标转推 url,带参数需要自行 url 转义 |
+ | retry_count | N | 转推失败重试次数,默认无限重试 |
+ | rtp_type | N | rtsp 推流时,推流方式,0:tcp,1:udp |
+ | timeout_sec | N | 推流超时时间,单位秒,float 类型 |
+- 响应:
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "key" : "rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12" # 流的唯一标识
+ }
+ }
+ ```
### 31、`/index/api/delStreamPusherProxy(可以使用close_streams接口关闭源直播流也可以停止推流)`
- - 功能:关闭推流
+- 功能:关闭推流
- - 范例:[http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12](http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12)
+- 范例:[http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/**defaultVhost**/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12](http://127.0.0.1/index/api/delStreamPusherProxy?key=rtmp/__defaultVhost__/proxy/test/4AB43C9EABEB76AB443BB8260C8B2D12)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | key | Y | addStreamPusherProxy接口返回的key |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :---------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | key | Y | addStreamPusherProxy 接口返回的 key |
- - 响应:
+- 响应:
+
+ ```json
+ {
+ "code" : 0,
+ "data" : {
+ "flag" : true # 成功与否
+ }
+ }
+ ```
- ```json
- {
- "code" : 0,
- "data" : {
- "flag" : true # 成功与否
- }
- }
- ```
### 32、`/index/api/version(获取版本信息)`
- - 功能:获取版本信息,如分支,commit id, 编译时间
+- 功能:获取版本信息,如分支,commit id, 编译时间
- - 范例:[http://127.0.0.1/index/api/version](http://127.0.0.1/index/api/version)
+- 范例:[http://127.0.0.1/index/api/version](http://127.0.0.1/index/api/version)
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
- - 响应:
+- 响应:
- ```json
- {
- "code": 0,
- "data": {
- "branchName": "master",
- "buildTime": "2023-04-19T10:34:34",
- "commitHash": "f143898"
- }
+ ```json
+ {
+ "code": 0,
+ "data": {
+ "branchName": "master",
+ "buildTime": "2023-04-19T10:34:34",
+ "commitHash": "f143898"
}
- ```
+ }
+ ```
### 33、`/index/api/getMediaPlayerList`
- - 功能:获取某个流观看者列表
+- 功能:获取某个流观看者列表
- - 范例:[http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test'](http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test')
+- 范例:[http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=**defaultVhost**&app=live&stream=test'](http://127.0.0.1:8080/index/api/getMediaPlayerList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&schema=rtsp&vhost=__defaultVhost__&app=live&stream=test')
- - 参数:
+- 参数:
- | 参数 | 是否必选 | 释意 |
- | :----: | :------: | :----------------------------------------------------------: |
- | secret | Y | api操作密钥(配置文件配置) |
- | schema | Y | 协议,例如 rtsp或rtmp |
- | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
- | app | Y | 应用名,例如 live |
- | stream | Y | 流id,例如 obs |
-
- - 响应:
+ | 参数 | 是否必选 | 释意 |
+ | :----: | :------: | :------------------------------: |
+ | secret | Y | api 操作密钥(配置文件配置) |
+ | schema | Y | 协议,例如 rtsp 或 rtmp |
+ | vhost | Y | 虚拟主机,例如`__defaultVhost__` |
+ | app | Y | 应用名,例如 live |
+ | stream | Y | 流 id,例如 obs |
- ```json
- {
- "code": 0,
- "data": [
- {
- "identifier": "3-309",
- "local_ip": "::",
- "local_port": 8000,
- "peer_ip": "172.18.190.159",
- "peer_port": 52996,
- "typeid": "mediakit::WebRtcSession"
- }
- ]
- }
- ```
+- 响应:
+
+```json
+{
+ "code": 0,
+ "data": [
+ {
+ "identifier": "3-309",
+ "local_ip": "::",
+ "local_port": 8000,
+ "peer_ip": "172.18.190.159",
+ "peer_port": 52996,
+ "typeid": "mediakit::WebRtcSession"
+ }
+ ]
+}
+```
diff --git a/src/zh/guide/media_server/sequence_diagram.md b/src/zh/guide/media_server/sequence_diagram.md
index dca0ec9..f2f3c82 100644
--- a/src/zh/guide/media_server/sequence_diagram.md
+++ b/src/zh/guide/media_server/sequence_diagram.md
@@ -6,12 +6,12 @@ title: 时序图
---
title: 按需拉流流程
---
-sequenceDiagram
+sequenceDiagram
participant 播放器
participant ZLMediaKit
participant 摄像头
participant 你的业务服务器
-
+
播放器 ->> ZLMediaKit : rtsp/rtmp/http-flv/ws-flv播放器请求
ZLMediaKit ->> ZLMediaKit:查找该流是否存在
ZLMediaKit ->> 你的业务服务器: 流不存在,触发web hook(stream_not_found)事件
@@ -37,7 +37,7 @@ sequenceDiagram
participant ZLMediaKit
participant 推流摄像头
participant 你的业务服务器
-
+
播放器 ->> ZLMediaKit : rtsp/rtmp/http-flv/ws-flv播放器请求
ZLMediaKit ->> ZLMediaKit:查找该流是否存在
ZLMediaKit ->> 你的业务服务器: 流不存在,触发web hook(stream_not_found)事件
@@ -50,7 +50,7 @@ sequenceDiagram
播放器 ->> ZLMediaKit:播放结束
ZLMediaKit ->> 你的业务服务器:无人观看流,触发web hook(stream_none_reader)事件
你的业务服务器 -->>ZLMediaKit:可以关闭推流
- ZLMediaKit ->> 推流摄像头:掐断推流
+ ZLMediaKit ->> 推流摄像头:掐断推流
```
```mermaid
@@ -61,7 +61,7 @@ sequenceDiagram
participant 播放器
participant ZLMediaKit
participant 你的业务服务器
-
+
播放器 ->> ZLMediaKit : rtsp/rtmp/http-flv/ws-flv/hls播放器请求
ZLMediaKit ->> 你的业务服务器: 是否有权播放,触发web hook(on_play)
你的业务服务器 -->> ZLMediaKit:参数合法,有权播放
@@ -76,7 +76,7 @@ sequenceDiagram
participant 推流器
participant ZLMediaKit
participant 你的业务服务器
-
+
推流器 ->> ZLMediaKit : rtsp/rtmp推流请求
ZLMediaKit ->> 你的业务服务器: 是否有权推流,触发web hook(on_publish)
你的业务服务器 -->> ZLMediaKit:参数合法,有权推流
diff --git a/src/zh/guide/media_server/start_server.md b/src/zh/guide/media_server/start_server.md
index addcbb3..fa3667f 100644
--- a/src/zh/guide/media_server/start_server.md
+++ b/src/zh/guide/media_server/start_server.md
@@ -4,13 +4,15 @@ icon: circle-info
---
## 程序所在路径
-在编译zlmediakit后,会生成MediaServer主程序,该程序相对路径为`release/${platform}/${build_type}/MediaServer`。
-`${platform}`根据您的操作系统,可能为`windows/linux/mac`,`${build_type}`根据您cmake时指定的编译类型,可能为`Debug/Release`.
+在编译 zlmediakit 后,会生成 MediaServer 主程序,该程序相对路径为`release/${platform}/${build_type}/MediaServer`。
+
+`${platform}`根据您的操作系统,可能为`windows/linux/mac`,`${build_type}`根据您 cmake 时指定的编译类型,可能为`Debug/Release`.
## 启动与参数
- 先参考启动参数帮助:
+
```bash
xzl-mac-pro:Debug xzl$ ./MediaServer -h
-h --help 无参 默认:null 选填 打印此信息
@@ -21,36 +23,33 @@ xzl-mac-pro:Debug xzl$ ./MediaServer -h
-s --ssl 有参 默认:/Users/xzl/git/ZLMediaKit/release/mac/Debug/ssl.p12 选填 ssl证书文件或文件夹,支持p12/pem类型
-t --threads 有参 默认:8 选填 启动事件触发线程数
```
+
- 说明:
+
- -d(--daemon): 是否以守护进程的方式启动,守护进程只做一件事,就是判断子进程(这个才是干活的进程)是否已经退出,退出后会不断尝试重启子进程。
- - -l(--level): 指定日志打印等级,赋值范围为0~4,等级越高,日志越少。
+ - -l(--level): 指定日志打印等级,赋值范围为 0~4,等级越高,日志越少。
- -m(--max_day): 日志文件保存天数,程序本次运行期间的日志如果超过这个天数,就会被删除。
- - -c(--config): 指定配置文件路径,配置文件为ini格式,请参考ZLMediaKit的默认配置文件。
- - -s(--ssl): 指定ssl证书路径,证书格式支持p12和pem类型,里面必须包含公钥和私钥,私钥不能有加密密码。如果指定文件夹,会加载文件夹下所有证书。
+ - -c(--config): 指定配置文件路径,配置文件为 ini 格式,请参考 ZLMediaKit 的默认配置文件。
+ - -s(--ssl): 指定 ssl 证书路径,证书格式支持 p12 和 pem 类型,里面必须包含公钥和私钥,私钥不能有加密密码。如果指定文件夹,会加载文件夹下所有证书。
- -t(--threads): 指定事件驱动线程(干重活)和后台工作线程(干阻塞的活)个数。
- 启动命令:
![图片](/images/start_server_1.png)
-
- 注意事项:
- - 1、如果你启动MediaServer后需要关闭shell,那么好需要输入 `exit`退出shell,否则关闭shell会导致MediaServer一起被关闭。
- - 2、如果你会使用到FFmpeg相关功能,你应该这样启动程序`nohup ./MediaServer -d &`,否则在fork FFmpeg进程时会导致MediaServer进程挂起。
-
+ - 1、如果你启动 MediaServer 后需要关闭 shell,那么好需要输入 `exit`退出 shell,否则关闭 shell 会导致 MediaServer 一起被关闭。
+ - 2、如果你会使用到 FFmpeg 相关功能,你应该这样启动程序`nohup ./MediaServer -d &`,否则在 fork FFmpeg 进程时会导致 MediaServer 进程挂起。
## 配置文件的热加载
-修改并保存配置文件后,在shell里面输入`killall -1 MediaServer`就能使ZLMediaKit热加载配置文件,如果生效,会打印下面样式的日志:
-![图片](/images/start_server_2.png)
+修改并保存配置文件后,在 shell 里面输入`killall -1 MediaServer`就能使 ZLMediaKit 热加载配置文件,如果生效,会打印下面样式的日志:
+![图片](/images/start_server_2.png)
## 关闭服务器
-- 如果你是后台启动方式,请在shell中输入`killall -2 MediaServer`以便优雅关闭服务器(程序收到SIGINT信号后会自动释放资源并退出)。
+
+- 如果你是后台启动方式,请在 shell 中输入`killall -2 MediaServer`以便优雅关闭服务器(程序收到 SIGINT 信号后会自动释放资源并退出)。
- 否则你可以同时按下`Ctr + C`退出程序。
-- MediaServer退出时日志如下:
+- MediaServer 退出时日志如下:
![图片](/images/start_server_3.png)
-
-
-
-
diff --git a/src/zh/guide/media_server/web_hook_api.md b/src/zh/guide/media_server/web_hook_api.md
index 0c44312..9162dd6 100644
--- a/src/zh/guide/media_server/web_hook_api.md
+++ b/src/zh/guide/media_server/web_hook_api.md
@@ -2,8 +2,9 @@
title: Web Hook 接口
---
-## HOOK预览
-MediaServer可以把内部的一些事件通过http post 第三方http服务器的方式通知出去,以下是相关的默认配置:
+## HOOK 预览
+
+MediaServer 可以把内部的一些事件通过 http post 第三方 http 服务器的方式通知出去,以下是相关的默认配置:
```ini
[hook]
@@ -27,34 +28,35 @@ on_server_keepalive=https://127.0.0.1/index/hook/on_server_keepalive
on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
```
-如果是鉴权事件,且访问IP是`127.0.0.1`或者鉴权url参数与`admin_params`一致,那么会直接鉴权成功(不会触发鉴权web hook)。
+如果是鉴权事件,且访问 IP 是`127.0.0.1`或者鉴权 url 参数与`admin_params`一致,那么会直接鉴权成功(不会触发鉴权 web hook)。
-大家也可以参考此[issue](https://github.com/zlmediakit/ZLMediaKit/issues/71)
+大家也可以参考此[issue](https://github.com/zlmediakit/ZLMediaKit/issues/71)
## 详解
+
### 1、enable :
- 解释:
- 是否开启http hook,如果选择关闭,ZLMediaKit将采取默认动作(例如不鉴权等)
+ 是否开启 http hook,如果选择关闭,ZLMediaKit 将采取默认动作(例如不鉴权等)
### 2、timeoutSec:
- 解释:
- 事件触发http post超时时间。
+ 事件触发 http post 超时时间。
### 3、admin_params:
- 解释:
- 超级管理员的url参数,如果访问者url参数与此一致,那么rtsp/rtmp/hls/http-flv/ws-flv播放或推流将无需鉴权。该选项用于开发者调试用。
+ 超级管理员的 url 参数,如果访问者 url 参数与此一致,那么 rtsp/rtmp/hls/http-flv/ws-flv 播放或推流将无需鉴权。该选项用于开发者调试用。
### 4、on_flow_report:
- 解释:
- 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件general.flowThreshold配置;此事件对回复不敏感。
+ 流量统计事件,播放器或推流器断开时并且耗用流量超过特定阈值时会触发此事件,阈值通过配置文件 general.flowThreshold 配置;此事件对回复不敏感。
- 触发请求:
@@ -68,7 +70,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -84,24 +86,23 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"id" : "140259799100960"
}
```
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :----------: | :------: | :--------------------------------------: |
- | `app` | `string` | 流应用名 |
- | `duration` | `int` | tcp链接维持时间,单位秒 |
- | `params` | `string` | 推流或播放url参数 |
- | `player` | `bool` | true为播放器,false为推流器 |
- | `schema` | `string` | 播放或推流的协议,可能是rtsp、rtmp、http |
- | `stream` | `string` | 流ID |
- | `totalBytes` | `int` | 耗费上下行流量总和,单位字节 |
- | `vhost` | `string` | 流虚拟主机 |
- | `ip` | `string` | 客户端ip |
- | `port` | `int` | 客户端端口号 |
- | `id` | `string` | TCP链接唯一ID |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :------: | :---------------------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `duration` | `int` | tcp 链接维持时间,单位秒 |
+ | `params` | `string` | 推流或播放 url 参数 |
+ | `player` | `bool` | true 为播放器,false 为推流器 |
+ | `schema` | `string` | 播放或推流的协议,可能是 rtsp、rtmp、http |
+ | `stream` | `string` | 流 ID |
+ | `totalBytes` | `int` | 耗费上下行流量总和,单位字节 |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `ip` | `string` | 客户端 ip |
+ | `port` | `int` | 客户端端口号 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
- 默认回复:
@@ -113,21 +114,19 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 07:09:32 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
-
- ```
-
+ ```
### 5、on_http_access:
- 解释:
- 访问http文件服务器上hls之外的文件时触发。
+ 访问 http 文件服务器上 hls 之外的文件时触发。
- 触发请求:
@@ -141,7 +140,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"header.Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
@@ -159,22 +158,22 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"path" : "/live/",
"port" : 65073
}
-
+
```
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :--------: | :--------------: | :-------------------------: |
- | `header.*` | `string` | http客户端请求header |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | http客户端ip |
- | `is_dir` | `bool` | http 访问路径是文件还是目录 |
- | `params` | `string` | http url参数 |
- | `path` | `string` | 请求访问的文件或目录 |
- | `port` | `unsigned short` | http客户端端口号 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :-------------------------: |
+ | `header.*` | `string` | http 客户端请求 header |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | http 客户端 ip |
+ | `is_dir` | `bool` | http 访问路径是文件还是目录 |
+ | `params` | `string` | http url 参数 |
+ | `path` | `string` | 请求访问的文件或目录 |
+ | `port` | `unsigned short` | http 客户端端口号 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -185,37 +184,34 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 07:27:01 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"err" : "",
"path" : "",
"second" : 600
}
-
+
```
- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :------: | :----------------------------------------------------------: |
- | `code` | `int` | 请固定返回0 |
- | `err` | `string` | 不允许访问的错误提示,允许访问请置空 |
- | `path` | `string` | 该客户端能访问或被禁止的顶端目录,如果为空字符串,则表述为当前目录 |
- | `second` | `int` | 本次授权结果的有效期,单位秒 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
-
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :------: | :----------------------------------------------------------------: |
+ | `code` | `int` | 请固定返回 0 |
+ | `err` | `string` | 不允许访问的错误提示,允许访问请置空 |
+ | `path` | `string` | 该客户端能访问或被禁止的顶端目录,如果为空字符串,则表述为当前目录 |
+ | `second` | `int` | 本次授权结果的有效期,单位秒 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
### 6、on_play:
- 解释:
- 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件;
- 如果流不存在,那么先触发on_play事件然后触发on_stream_not_found事件。
- 播放rtsp流时,如果该流启动了rtsp专属鉴权(on_rtsp_realm)那么将不再触发on_play事件。
-
+ 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls 的播放都将触发此鉴权事件;
+ 如果流不存在,那么先触发 on_play 事件然后触发 on_stream_not_found 事件。
+ 播放 rtsp 流时,如果该流启动了 rtsp 专属鉴权(on_rtsp_realm)那么将不再触发 on_play 事件。
+
- 触发请求:
```http
@@ -228,7 +224,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -240,23 +236,23 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"stream" : "obs",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :--------------: | :--------------------------------: |
- | `app` | `string` | 流应用名 |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | 播放器ip |
- | `params` | `string` | 播放url参数 |
- | `port` | `unsigned short` | 播放器端口号 |
- | `schema` | `string` | 播放的协议,可能是rtsp、rtmp、http |
- | `stream` | `string` | 流ID |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :---------------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | 播放器 ip |
+ | `params` | `string` | 播放 url 参数 |
+ | `port` | `unsigned short` | 播放器端口号 |
+ | `schema` | `string` | 播放的协议,可能是 rtsp、rtmp、http |
+ | `stream` | `string` | 流 ID |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -267,29 +263,27 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 07:41:21 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
-
- ```
-
-- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :----: | :------: | :---------------------: |
- | `code` | `int` | 错误代码,0代表允许播放 |
- | `msg` | `string` | 不允许播放时的错误提示 |
-
+ ```
+- 回复参数详解:
+ | 参数名 | 参数类型 | 参数解释 |
+ | :----: | :------: | :----------------------: |
+ | `code` | `int` | 错误代码,0 代表允许播放 |
+ | `msg` | `string` | 不允许播放时的错误提示 |
### 7、on_publish:
- 解释:
- rtsp/rtmp/rtp推流鉴权事件。
+ rtsp/rtmp/rtp 推流鉴权事件。
+
- 触发请求:
```http
@@ -302,7 +296,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -314,23 +308,23 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"stream" : "obs",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :--------------: | :--------------------------: |
- | `app` | `string` | 流应用名 |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | 推流器ip |
- | `params` | `string` | 推流url参数 |
- | `port` | `unsigned short` | 推流器端口号 |
- | `schema` | `string` | 推流的协议,可能是rtsp、rtmp |
- | `stream` | `string` | 流ID |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :---------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | 推流器 ip |
+ | `params` | `string` | 推流 url 参数 |
+ | `port` | `unsigned short` | 推流器端口号 |
+ | `schema` | `string` | 推流的协议,可能是 rtsp、rtmp |
+ | `stream` | `string` | 流 ID |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -341,7 +335,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 07:46:43 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"add_mute_audio" : true,
@@ -362,43 +356,43 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"auto_close" : false,
"stream_replace" : ""
}
-
+
```
-
+
- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 | 必须参数 |
- | :----------------: | :------: | :----------------------------------------------------------: | :------: |
- | `code` | `int` | 错误代码,0代表允许推流 | Y |
- | `msg` | `string` | 不允许推流时的错误提示 | Y |
- | `enable_hls` | `bool` | 是否转换成hls-mpegts协议 | N |
- | `enable_hls_fmp4` | `bool` | 是否转换成hls-fmp4协议 | N |
- | `enable_mp4` | `bool` | 是否允许mp4录制 | N |
- | `enable_rtsp` | `bool` | 是否转rtsp协议 | N |
- | `enable_rtmp` | `bool` | 是否转rtmp/flv协议 | N |
- | `enable_ts` | `bool` | 是否转http-ts/ws-ts协议 | N |
- | `enable_fmp4` | `bool` | 是否转http-fmp4/ws-fmp4协议 | N |
- | `hls_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `rtsp_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `rtmp_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `ts_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `fmp4_demand` | `bool` | 该协议是否有人观看才生成 | N |
- | `enable_audio` | `bool` | 转协议时是否开启音频 | N |
- | `add_mute_audio` | `bool` | 转协议时,无音频是否添加静音aac音频 | N |
- | `mp4_save_path` | `string` | mp4录制文件保存根目录,置空使用默认 | N |
- | `mp4_max_second` | `int` | mp4录制切片大小,单位秒 | N |
- | `mp4_as_player` | `bool` | MP4录制是否当作观看者参与播放人数计数 | N |
- | `hls_save_path` | `string` | hls文件保存保存根目录,置空使用默认 | N |
- | `modify_stamp` | `int` | 该流是否开启时间戳覆盖(0:绝对时间戳/1:系统时间戳/2:相对时间戳) | N |
- | `continue_push_ms` | `uint32` | 断连续推延时,单位毫秒,置空使用配置文件默认值 | N |
- | `auto_close` | `bool` | 无人观看是否自动关闭流(不触发无人观看hook) | N |
- | `stream_replace` | `string` | 是否修改流id, 通过此参数可以自定义流id(譬如替换ssrc) | N |
+ | 参数名 | 参数类型 | 参数解释 | 必须参数 |
+ | :----------------: | :------: | :------------------------------------------------------------: | :------: |
+ | `code` | `int` | 错误代码,0 代表允许推流 | Y |
+ | `msg` | `string` | 不允许推流时的错误提示 | Y |
+ | `enable_hls` | `bool` | 是否转换成 hls-mpegts 协议 | N |
+ | `enable_hls_fmp4` | `bool` | 是否转换成 hls-fmp4 协议 | N |
+ | `enable_mp4` | `bool` | 是否允许 mp4 录制 | N |
+ | `enable_rtsp` | `bool` | 是否转 rtsp 协议 | N |
+ | `enable_rtmp` | `bool` | 是否转 rtmp/flv 协议 | N |
+ | `enable_ts` | `bool` | 是否转 http-ts/ws-ts 协议 | N |
+ | `enable_fmp4` | `bool` | 是否转 http-fmp4/ws-fmp4 协议 | N |
+ | `hls_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `rtsp_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `rtmp_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `ts_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `fmp4_demand` | `bool` | 该协议是否有人观看才生成 | N |
+ | `enable_audio` | `bool` | 转协议时是否开启音频 | N |
+ | `add_mute_audio` | `bool` | 转协议时,无音频是否添加静音 aac 音频 | N |
+ | `mp4_save_path` | `string` | mp4 录制文件保存根目录,置空使用默认 | N |
+ | `mp4_max_second` | `int` | mp4 录制切片大小,单位秒 | N |
+ | `mp4_as_player` | `bool` | MP4 录制是否当作观看者参与播放人数计数 | N |
+ | `hls_save_path` | `string` | hls 文件保存保存根目录,置空使用默认 | N |
+ | `modify_stamp` | `int` | 该流是否开启时间戳覆盖(0:绝对时间戳/1:系统时间戳/2:相对时间戳) | N |
+ | `continue_push_ms` | `uint32` | 断连续推延时,单位毫秒,置空使用配置文件默认值 | N |
+ | `auto_close` | `bool` | 无人观看是否自动关闭流(不触发无人观看 hook) | N |
+ | `stream_replace` | `string` | 是否修改流 id, 通过此参数可以自定义流 id(譬如替换 ssrc) | N |
### 8、on_record_mp4:
- 解释:
- 录制mp4完成后通知事件;此事件对回复不敏感。
+ 录制 mp4 完成后通知事件;此事件对回复不敏感。
- 触发请求:
@@ -412,7 +406,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -427,23 +421,23 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost" : "__defaultVhost__"
}
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :----------: | :------: | :---------------------------: |
- | `app` | `string` | 录制的流应用名 |
- | `file_name` | `string` | 文件名 |
- | `file_path` | `string` | 文件绝对路径 |
- | `file_size` | `int` | 文件大小,单位字节 |
- | `folder` | `string` | 文件所在目录路径 |
- | `start_time` | `int` | 开始录制时间戳 |
- | `stream` | `string` | 录制的流ID |
- | `time_len` | `float` | 录制时长,单位秒 |
- | `url` | `string` | http/rtsp/rtmp点播相对url路径 |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :------: | :------------------------------: |
+ | `app` | `string` | 录制的流应用名 |
+ | `file_name` | `string` | 文件名 |
+ | `file_path` | `string` | 文件绝对路径 |
+ | `file_size` | `int` | 文件大小,单位字节 |
+ | `folder` | `string` | 文件所在目录路径 |
+ | `start_time` | `int` | 开始录制时间戳 |
+ | `stream` | `string` | 录制的流 ID |
+ | `time_len` | `float` | 录制时长,单位秒 |
+ | `url` | `string` | http/rtsp/rtmp 点播相对 url 路径 |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -454,23 +448,20 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 07:53:13 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-
-
### 9、on_rtsp_realm:
- 解释:
- 该rtsp流是否开启rtsp专用方式的鉴权事件,开启后才会触发on_rtsp_auth事件。
+ 该 rtsp 流是否开启 rtsp 专用方式的鉴权事件,开启后才会触发 on_rtsp_auth 事件。
- 需要指出的是rtsp也支持url参数鉴权,它支持两种方式鉴权。
+ 需要指出的是 rtsp 也支持 url 参数鉴权,它支持两种方式鉴权。
- 触发请求:
@@ -484,7 +475,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -497,21 +488,21 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost" : "__defaultVhost__"
}
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :--------------: | :--------------: |
- | `app` | `string` | 流应用名 |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | rtsp播放器ip |
- | `params` | `string` | 播放rtsp url参数 |
- | `port` | `unsigned short` | rtsp播放器端口号 |
- | `schema` | `string` | rtsp或rtsps |
- | `stream` | `string` | 流ID |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | rtsp 播放器 ip |
+ | `params` | `string` | 播放 rtsp url 参数 |
+ | `port` | `unsigned short` | rtsp 播放器端口号 |
+ | `schema` | `string` | rtsp 或 rtsps |
+ | `stream` | `string` | 流 ID |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -522,29 +513,26 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:05:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"realm" : "zlmediakit_reaml"
}
-
- ```
-
-- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :-----: | :------: | :--------------------------------------------------: |
- | `code` | `int` | 请固定返回0 |
- | `realm` | `string` | 该rtsp流是否需要rtsp专有鉴权,空字符串代码不需要鉴权 |
-
+ ```
+- 回复参数详解:
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-----: | :------: | :------------------------------------------------------: |
+ | `code` | `int` | 请固定返回 0 |
+ | `realm` | `string` | 该 rtsp 流是否需要 rtsp 专有鉴权,空字符串代码不需要鉴权 |
### 10、on_rtsp_auth:
- 解释:
- rtsp专用的鉴权事件,先触发on_rtsp_realm事件然后才会触发on_rtsp_auth事件。
+ rtsp 专用的鉴权事件,先触发 on_rtsp_realm 事件然后才会触发 on_rtsp_auth 事件。
- 触发请求:
@@ -558,7 +546,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -573,26 +561,26 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"user_name" : "test",
"vhost" : "__defaultVhost__"
}
-
+
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :---------------: | :--------------: | :----------------------------------------------: |
- | `app` | `string` | 流应用名 |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | rtsp播放器ip |
- | `must_no_encrypt` | `bool` | 请求的密码是否必须为明文(base64鉴权需要明文密码) |
- | `params` | `string` | rtsp url参数 |
- | `port` | `unsigned short` | rtsp播放器端口号 |
- | `realm` | `string` | rtsp播放鉴权加密realm |
- | `schema` | `string` | rtsp或rtsps |
- | `stream` | `string` | 流ID |
- | `user_name` | `string` | 播放用户名 |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :---------------: | :--------------: | :-----------------------------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | rtsp 播放器 ip |
+ | `must_no_encrypt` | `bool` | 请求的密码是否必须为明文(base64 鉴权需要明文密码) |
+ | `params` | `string` | rtsp url 参数 |
+ | `port` | `unsigned short` | rtsp 播放器端口号 |
+ | `realm` | `string` | rtsp 播放鉴权加密 realm |
+ | `schema` | `string` | rtsp 或 rtsps |
+ | `stream` | `string` | 流 ID |
+ | `user_name` | `string` | 播放用户名 |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -603,33 +591,31 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:05:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"encrypted" : false,
"passwd" : "test"
}
-
+
```
-
+
- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :---------: | :------: | :----------------------: |
- | `code` | `int` | 错误代码,0代表允许播放 |
- | `msg` | `string` | 播放鉴权失败时的错误提示 |
- | `encrypted` | `bool` | 用户密码是明文还是摘要 |
+ | 参数名 | 参数类型 | 参数解释 |
+ | :---------: | :------: | :----------------------------------------------: |
+ | `code` | `int` | 错误代码,0 代表允许播放 |
+ | `msg` | `string` | 播放鉴权失败时的错误提示 |
+ | `encrypted` | `bool` | 用户密码是明文还是摘要 |
| `passwd` | `string` | 用户密码明文或摘要(md5(username:realm:password)) |
-
-
### 11、on_shell_login:
- 解释:
- shell登录鉴权,ZLMediaKit提供简单的telnet调试方式
-
- 使用`telnet 127.0.0.1 9000`能进入MediaServer进程的shell界面。
+ shell 登录鉴权,ZLMediaKit 提供简单的 telnet 调试方式
+
+ 使用`telnet 127.0.0.1 9000`能进入 MediaServer 进程的 shell 界面。
- 触发请求:
@@ -643,7 +629,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"id" : "140227419332496",
@@ -653,18 +639,18 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"user_name" : "xzl"
}
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :---------: | :--------------: | :---------------------: |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | telnet 终端ip |
- | `passwd` | `bool` | telnet 终端登录用户密码 |
- | `port` | `unsigned short` | telnet 终端端口号 |
- | `user_name` | `string` | telnet 终端登录用户名 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :------------------------: |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | telnet 终端 ip |
+ | `passwd` | `bool` | telnet 终端登录用户密码 |
+ | `port` | `unsigned short` | telnet 终端端口号 |
+ | `user_name` | `string` | telnet 终端登录用户名 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -675,31 +661,30 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:23:00 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-- 回复参数详解:
-
- | 参数名 | 参数类型 | 参数解释 |
- | :----: | :------: | :---------------------------: |
- | `code` | `int` | 错误代码,0代表允许登录telnet |
- | `msg` | `string` | 不允许登录telnet时的错误提示 |
-
+- 回复参数详解:
+ | 参数名 | 参数类型 | 参数解释 |
+ | :----: | :------: | :-----------------------------: |
+ | `code` | `int` | 错误代码,0 代表允许登录 telnet |
+ | `msg` | `string` | 不允许登录 telnet 时的错误提示 |
### 12、on_stream_changed:
- 解释:
- rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
+ rtsp/rtmp 流注册或注销时触发此事件;此事件对回复不敏感。
- 触发请求:
+
- 注销时:
+
```http
POST /index/hook/on_stream_changed HTTP/1.1
Accept: */*
@@ -710,7 +695,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -720,7 +705,9 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost" : "__defaultVhost__"
}
```
+
- 注册时:
+
```http
POST /index/hook/on_stream_changed HTTP/1.1
Accept: */*
@@ -731,7 +718,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"regist" : true,
"aliveSecond": 0, #存活时间,单位秒
@@ -756,7 +743,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"tracks": [{
"channels" : 1, # 音频通道数
"codec_id" : 2, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecAAC", # 编码类型名称
+ "codec_id_name" : "CodecAAC", # 编码类型名称
"codec_type" : 1, # Video = 0, Audio = 1
"ready" : true, # 轨道是否准备就绪
"sample_bit" : 16, # 音频采样位数
@@ -764,7 +751,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
},
{
"codec_id" : 0, # H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
- "codec_id_name" : "CodecH264", # 编码类型名称
+ "codec_id_name" : "CodecH264", # 编码类型名称
"codec_type" : 0, # Video = 0, Audio = 1
"fps" : 59, # 视频fps
"height" : 720, # 视频高
@@ -774,18 +761,18 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost": "__defaultVhost__"
}
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :------: | :----------: |
- | `app` | `string` | 流应用名 |
- | `regist` | `bool` | 流注册或注销 |
- | `schema` | `string` | rtsp或rtmp |
- | `stream` | `string` | 流ID |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
-
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :------: | :------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `regist` | `bool` | 流注册或注销 |
+ | `schema` | `string` | rtsp 或 rtmp |
+ | `stream` | `string` | 流 ID |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
+
- 默认回复:
```http
@@ -796,24 +783,21 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:27:35 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success"
}
```
-
-
-
### 13、on_stream_none_reader:
- 解释:
- 流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流。
- 一个直播流注册上线了,如果一直没人观看也会触发一次无人观看事件,触发时的协议schema是随机的,看哪种协议最晚注册(一般为hls)。
- 后续从有人观看转为无人观看,触发协议schema为最后一名观看者使用何种协议。
- 目前mp4/hls录制不当做观看人数(mp4录制可以通过配置文件mp4_as_player控制,但是rtsp/rtmp/rtp转推算观看人数,也会触发该事件。
+ 流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流。
+ 一个直播流注册上线了,如果一直没人观看也会触发一次无人观看事件,触发时的协议 schema 是随机的,看哪种协议最晚注册(一般为 hls)。
+ 后续从有人观看转为无人观看,触发协议 schema 为最后一名观看者使用何种协议。
+ 目前 mp4/hls 录制不当做观看人数(mp4 录制可以通过配置文件 mp4_as_player 控制,但是 rtsp/rtmp/rtp 转推算观看人数,也会触发该事件。
- 触发请求:
@@ -827,7 +811,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -836,16 +820,16 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost" : "__defaultVhost__"
}
```
-
+
- 请求参数详解:
-| 参数名 | 参数类型 | 参数解释 |
-| :------: | :------: | :--------: |
-| `app` | `string` | 流应用名 |
-| `schema` | `string` | rtsp或rtmp |
-| `stream` | `string` | 流ID |
-| `vhost` | `string` | 流虚拟主机 |
-| `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
+| 参数名 | 参数类型 | 参数解释 |
+| :-------------: | :------: | :------------------------: |
+| `app` | `string` | 流应用名 |
+| `schema` | `string` | rtsp 或 rtmp |
+| `stream` | `string` | 流 ID |
+| `vhost` | `string` | 流虚拟主机 |
+| `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
- 默认回复:
@@ -857,28 +841,25 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:51:23 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"close" : true,
"code" : 0
}
```
-
+
- 回复参数详解:
- | 参数名 | 参数类型 | 参数解释 |
+ | 参数名 | 参数类型 | 参数解释 |
| :-----: | :------: | :----------------: |
- | `code` | `int` | 请固定返回0 |
+ | `code` | `int` | 请固定返回 0 |
| `close` | `bool` | 是否关闭推流或拉流 |
-
-
-
### 14、on_stream_not_found:
- 解释:
- 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。
+ 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。
- 触发请求:
@@ -892,7 +873,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"mediaServerId" : "your_server_id",
"app" : "live",
@@ -905,20 +886,20 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"vhost" : "__defaultVhost__"
}
```
-
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :--------------: | :--------------------------: |
- | `app` | `string` | 流应用名 |
- | `id` | `string` | TCP链接唯一ID |
- | `ip` | `string` | 播放器ip |
- | `params` | `string` | 播放url参数 |
- | `port` | `unsigned short` | 播放器端口号 |
- | `schema` | `string` | 播放的协议,可能是rtsp、rtmp |
- | `stream` | `string` | 流ID |
- | `vhost` | `string` | 流虚拟主机 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :--------------: | :---------------------------: |
+ | `app` | `string` | 流应用名 |
+ | `id` | `string` | TCP 链接唯一 ID |
+ | `ip` | `string` | 播放器 ip |
+ | `params` | `string` | 播放 url 参数 |
+ | `port` | `unsigned short` | 播放器端口号 |
+ | `schema` | `string` | 播放的协议,可能是 rtsp、rtmp |
+ | `stream` | `string` | 流 ID |
+ | `vhost` | `string` | 流虚拟主机 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
- 默认回复:
@@ -930,20 +911,18 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:55:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success
}
```
-
-
-
### 15、on_server_started
+
- 解释:
- 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。
+ 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。
- 触发请求:
@@ -957,7 +936,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Host: 127.0.0.1
Tools: ZLMediaKit
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
+
{
"api.apiDebug" : "1",
"api.secret" : "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
@@ -1034,9 +1013,9 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
"shell.port" : "9000"
}
```
-
+
- 请求参数详解:
- 配置文件json对象
+ 配置文件 json 对象
- 默认回复:
@@ -1048,7 +1027,7 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
Date: Fri, Sep 20 2019 08:55:49 GMT
Keep-Alive: timeout=10, max=100
Server: ZLMediaKit-4.0
-
+
{
"code" : 0,
"msg" : "success
@@ -1059,77 +1038,80 @@ on_rtp_server_timeout=https://127.0.0.1/index/hook/on_rtp_server_timeout
- 解释:
- 服务器定时上报时间,上报间隔可配置,默认10s上报一次
+ 服务器定时上报时间,上报间隔可配置,默认 10s 上报一次
- 触发请求
- ```http
- POST /index/hook/on_server_keepalive HTTP/1.1
- Accept: */*
- Accept-Language: zh-CN,zh;q=0.8
- Connection: keep-alive
- Content-Length: 189
- Content-Type: application/json
- Host: 127.0.0.1
- Tools: ZLMediaKit
- User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
- {
- "data" : {
- "Buffer" : 12,
- "BufferLikeString" : 0,
- "BufferList" : 0,
- "BufferRaw" : 12,
- "Frame" : 0,
- "FrameImp" : 0,
- "MediaSource" : 0,
- "MultiMediaSourceMuxer" : 0,
- "RtmpPacket" : 0,
- "RtpPacket" : 0,
- "Socket" : 108,
- "TcpClient" : 0,
- "TcpServer" : 96,
- "TcpSession" : 0,
- "UdpServer" : 12,
- "UdpSession" : 0
- },
- "mediaServerId" : "192.168.255.10"
- }
- ```
+ ```http
+ POST /index/hook/on_server_keepalive HTTP/1.1
+ Accept: */*
+ Accept-Language: zh-CN,zh;q=0.8
+ Connection: keep-alive
+ Content-Length: 189
+ Content-Type: application/json
+ Host: 127.0.0.1
+ Tools: ZLMediaKit
+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
+
+ {
+ "data" : {
+ "Buffer" : 12,
+ "BufferLikeString" : 0,
+ "BufferList" : 0,
+ "BufferRaw" : 12,
+ "Frame" : 0,
+ "FrameImp" : 0,
+ "MediaSource" : 0,
+ "MultiMediaSourceMuxer" : 0,
+ "RtmpPacket" : 0,
+ "RtpPacket" : 0,
+ "Socket" : 108,
+ "TcpClient" : 0,
+ "TcpServer" : 96,
+ "TcpSession" : 0,
+ "UdpServer" : 12,
+ "UdpSession" : 0
+ },
+ "mediaServerId" : "192.168.255.10"
+ }
+ ```
+
### 17、on_rtp_server_timeout
- 解释:
- 调用openRtpServer 接口,rtp server 长时间未收到数据,执行此web hook,对回复不敏感
+ 调用 openRtpServer 接口,rtp server 长时间未收到数据,执行此 web hook,对回复不敏感
- 触发请求
- ```http
- POST /index/hook/on_rtp_server_timeout HTTP/1.1
- Accept: */*
- Accept-Language: zh-CN,zh;q=0.8
- Connection: keep-alive
- Content-Length: 189
- Content-Type: application/json
- Host: 127.0.0.1
- Tools: ZLMediaKit
- User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
-
- {
- "local_port" : 0,
- "re_use_port" : true,
- "ssrc" : 0,
- "stream_id" : "test",
- "tcp_mode" : 0,
- "mediaServerId" : "192.168.255.10"
- }
+ ```http
+ POST /index/hook/on_rtp_server_timeout HTTP/1.1
+ Accept: */*
+ Accept-Language: zh-CN,zh;q=0.8
+ Connection: keep-alive
+ Content-Length: 189
+ Content-Type: application/json
+ Host: 127.0.0.1
+ Tools: ZLMediaKit
+ User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
+
+ {
+ "local_port" : 0,
+ "re_use_port" : true,
+ "ssrc" : 0,
+ "stream_id" : "test",
+ "tcp_mode" : 0,
+ "mediaServerId" : "192.168.255.10"
+ }
+ ```
+
- 请求参数详解:
- | 参数名 | 参数类型 | 参数解释 |
- | :------: | :--------------: | :--------------------------: |
- | `local_port` | `int` | openRtpServer 输入的参数 |
- | `re_use_port` | `bool` | openRtpServer 输入的参数 |
- | `ssrc` | `uint32` | openRtpServer 输入的参数 |
- | `stream_id` | `string` | openRtpServer 输入的参数 |
- | `tcp_mode` | `int` | openRtpServer 输入的参数 |
- | `mediaServerId` | `string` | 服务器id,通过配置文件设置 |
+ | 参数名 | 参数类型 | 参数解释 |
+ | :-------------: | :------: | :------------------------: |
+ | `local_port` | `int` | openRtpServer 输入的参数 |
+ | `re_use_port` | `bool` | openRtpServer 输入的参数 |
+ | `ssrc` | `uint32` | openRtpServer 输入的参数 |
+ | `stream_id` | `string` | openRtpServer 输入的参数 |
+ | `tcp_mode` | `int` | openRtpServer 输入的参数 |
+ | `mediaServerId` | `string` | 服务器 id,通过配置文件设置 |
diff --git a/src/zh/guide/protocol/README.md b/src/zh/guide/protocol/README.md
index 6dc3c65..301cb37 100644
--- a/src/zh/guide/protocol/README.md
+++ b/src/zh/guide/protocol/README.md
@@ -4,8 +4,4 @@ icon: lightbulb
index: false
---
-## Introduction
-
-We support foo feature, ...
-
-
+
diff --git a/src/zh/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md b/src/zh/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
index cd79461..cd02ad2 100644
--- a/src/zh/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
+++ b/src/zh/guide/protocol/gb28181/gb28181_sip_signaling_packet_capture.md
@@ -3,7 +3,9 @@ title: GB28181 SIP信令抓包
---
## 1、注册
+
- 注册请求:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK4162288924
@@ -18,7 +20,8 @@ Expires: 7200
Content-Length: 0
```
-- 回复401:
+- 回复 401:
+
```http
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK4162288924
@@ -33,6 +36,7 @@ Content-Length: 0
```
- 再次注册:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK3997518011
@@ -47,7 +51,9 @@ User-Agent: Hikvision
Expires: 7200
Content-Length: 0
```
+
- 注册成功:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK3997518011
@@ -61,9 +67,10 @@ Date: 2013-09-10T16:01:51
Content-Length: 0
```
-
## 2、注销
+
- 注销请求:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK1670314216
@@ -78,7 +85,8 @@ Expires: 0
Content-Length: 0
```
-- 回复401:
+- 回复 401:
+
```http
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK1670314216
@@ -93,6 +101,7 @@ Content-Length: 0
```
- 再次注销:
+
```http
REGISTER sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK317693249
@@ -109,6 +118,7 @@ Content-Length: 0
```
- 注销成功:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK317693249
@@ -122,9 +132,10 @@ Date: 2013-09-10T14:04:41
Content-Length: 0
```
-
## 3、心跳
+
- 请求:
+
```http
MESSAGE sip:130909115229300920@10.64.49.44:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.218:7100;rport;branch=z9hG4bK2672759896
@@ -147,6 +158,7 @@ Content-Length: 150
```
- 回复:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.218:7100;rport=7100;branch=z9hG4bK2672759896
@@ -158,9 +170,10 @@ User-Agent: Hikvision
Content-Length: 0
```
-
## 4、目录检索
+
- 请求:
+
```http
MESSAGE sip:130909113319427420@10.64.49.218:7100 SIP/2.0
Via: SIP/2.0/UDP 10.64.49.44:7100;rport;branch=z9hG4bK32925498
@@ -180,7 +193,9 @@ Content-Length: 124
130909113319427420
```
+
- 回复:
+
```http
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.64.49.44:7100;rport=7100;branch=z9hG4bK32925498
diff --git a/src/zh/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md b/src/zh/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
index ce88de8..778267a 100644
--- a/src/zh/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
+++ b/src/zh/guide/protocol/gb28181/how_to_use_device_id_as_stream_id.md
@@ -1,24 +1,30 @@
---
title: GB28181怎么用设备ID作为流ID
---
-为了支持RTP流的识别(与摄像头ID产生关联), 必须通过 `源地址` 或 `ssrc` 或 `本地端口号` 来区分.
-但是在issue #338 里面有开发者反馈,有些设备不支持设置ssrc,ssrc一直为0.
+为了支持 RTP 流的识别(与摄像头 ID 产生关联), 必须通过 `源地址` 或 `ssrc` 或 `本地端口号` 来区分.
-而源地址端口也会一直变,RTP推流前SIP服务器也不知道摄像头推流端口(甚至IP都不知道) 那么区分流只通过源地址也不现实,
-因为一个局域网内也可能多个设备, 如果ZLMediaKit在公网,那么这些流的IP是一致的,而端口是随机的,根本没法跟摄像头ID对应起来.
+但是在 issue #338 里面有开发者反馈,有些设备不支持设置 ssrc,ssrc 一直为 0.
-所以为了实现RTP推流参数的流ID与摄像头ID产生关联,就基本只剩下`本地端口号`这条路了,这就意味着一个端口只能接受一个流。
+而源地址端口也会一直变,RTP 推流前 SIP 服务器也不知道摄像头推流端口(甚至 IP 都不知道) 那么区分流只通过源地址也不现实,
+因为一个局域网内也可能多个设备, 如果 ZLMediaKit 在公网,那么这些流的 IP 是一致的,而端口是随机的,根本没法跟摄像头 ID 对应起来.
-在不指定流ID时,ZLMediaKit的行为跟之前完全一样,单端口支持多流,ssrc作为stream id。
+所以为了实现 RTP 推流参数的流 ID 与摄像头 ID 产生关联,就基本只剩下`本地端口号`这条路了,这就意味着一个端口只能接受一个流。
-如果指定了该端口绑定的流ID,那么该端口只能接收一路流。
+在不指定流 ID 时,ZLMediaKit 的行为跟之前完全一样,单端口支持多流,ssrc 作为 stream id。
+
+如果指定了该端口绑定的流 ID,那么该端口只能接收一路流。
以下是关键代码:
+
![image](/images/how_to_use_device_id_as_stream_id_1.png)
+
![image](/images/how_to_use_device_id_as_stream_id_2.png)
+
![image](/images/how_to_use_device_id_as_stream_id_3.png)
+
![image](/images/how_to_use_device_id_as_stream_id_4.png)
+
![image](/images/how_to_use_device_id_as_stream_id_5.png)
-![image](/images/how_to_use_device_id_as_stream_id_6.png)
+![image](/images/how_to_use_device_id_as_stream_id_6.png)
diff --git a/src/zh/guide/protocol/gb28181/push_streaming.md b/src/zh/guide/protocol/gb28181/push_streaming.md
index 1ed2c0f..cb9df7a 100644
--- a/src/zh/guide/protocol/gb28181/push_streaming.md
+++ b/src/zh/guide/protocol/gb28181/push_streaming.md
@@ -1,91 +1,97 @@
---
title: GB28181推流
---
+
## 介绍
-ZLMediaKit支持GB28181的 ps-rtp推流,支持的编码格式分别为 `h264/h265/aac/g711/opus`。
-在收到GB28181推流后,ZLMediaKit会依次做以下事情:
-- rtp排序去重。
-- rtp解析成ps或ts。
-- ps或ts解析成`h264/h265/aac/g711/opus`。
-- 输入到复用器,生成rtsp/rtmp/ts/fmp4等格式,以便转换成其他协议或容器。
+ZLMediaKit 支持 GB28181 的 ps-rtp 推流,支持的编码格式分别为 `h264/h265/aac/g711/opus`。
+在收到 GB28181 推流后,ZLMediaKit 会依次做以下事情:
+
+- rtp 排序去重。
+- rtp 解析成 ps 或 ts。
+- ps 或 ts 解析成`h264/h265/aac/g711/opus`。
+- 输入到复用器,生成 rtsp/rtmp/ts/fmp4 等格式,以便转换成其他协议或容器。
## 简单使用
-ZLMediaKit默认开启10000端口用于接收UDP/TCP的GB28181推流,由于国标推流不好测试,ZLMediaKit同时也支持rtp_mpegts推流,代码会自适应判断是否为ps还是ts。
-所以如果大家没有摄像头的情况下,可以用FFmpeg简单测试,基本上体验跟国标推流并无二致。
-- ffmpeg推流命令:
+ZLMediaKit 默认开启 10000 端口用于接收 UDP/TCP 的 GB28181 推流,由于国标推流不好测试,ZLMediaKit 同时也支持 rtp_mpegts 推流,代码会自适应判断是否为 ps 还是 ts。
+所以如果大家没有摄像头的情况下,可以用 FFmpeg 简单测试,基本上体验跟国标推流并无二致。
+
+- ffmpeg 推流命令:
+
```bash
ffmpeg -re -i www/record/robot.mp4 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:10000
```
-- MediaServer收到推流后的日志:
-![图片](/images/gb28181_push_streaming_1.png)
+- MediaServer 收到推流后的日志:
+ ![图片](/images/gb28181_push_streaming_1.png)
-上图中,这个推流的rtp ssrc为BFC2C622(16进制打印),这个流的app为`rtp`, stream_id为`BFC2C622`,您可以根据[wiki](../../media_server/play_url_rules.md)来组合成url并播放这个流。
+上图中,这个推流的 rtp ssrc 为 BFC2C622(16 进制打印),这个流的 app 为`rtp`, stream_id 为`BFC2C622`,您可以根据[wiki](../../media_server/play_url_rules.md)来组合成 url 并播放这个流。
-需要指出的是,国标推流的app固定为rtp,你只能通过代码来修改它,stream_id为rtp流的ssrc,这个是随机的,在FFmpeg中貌似没法控制。
-
-另外,每次推流时,请更换ssrc,否则ZLMediaKit发现推流端ip和端口变化后,会直接丢弃rtp包(现象如此[issue](https://github.com/xia-chu/ZLMediaKit/issues/267));这样做的目的是为了防止两个设备使用同一个ssrc推流时互相干扰。
+需要指出的是,国标推流的 app 固定为 rtp,你只能通过代码来修改它,stream_id 为 rtp 流的 ssrc,这个是随机的,在 FFmpeg 中貌似没法控制。
+另外,每次推流时,请更换 ssrc,否则 ZLMediaKit 发现推流端 ip 和端口变化后,会直接丢弃 rtp 包(现象如此[issue](https://github.com/xia-chu/ZLMediaKit/issues/267));这样做的目的是为了防止两个设备使用同一个 ssrc 推流时互相干扰。
## 高阶使用
-在推流给10000端口时,您可能发现有个缺陷,就是stream_id是ssrc,比较抽象,可能还没法控制。
-那么我们能否自定义stream_id? 答案是肯定的,ZLMediaKit通过[restful api](../../media_server/restful_api.md#24indexapiopenrtpserver)可以动态开启国标收流端口(同时支持udp/tcp模式)。
+在推流给 10000 端口时,您可能发现有个缺陷,就是 stream_id 是 ssrc,比较抽象,可能还没法控制。
+
+那么我们能否自定义 stream_id? 答案是肯定的,ZLMediaKit 通过[restful api](../../media_server/restful_api.md#24indexapiopenrtpserver)可以动态开启国标收流端口(同时支持 udp/tcp 模式)。
+
+在使用 openRtpServer 接口动态开启国标收流端口后,这个端口只能产生一个流,也就是说,一个摄像头需要一个服务器端口用于接收国标推流。
-在使用openRtpServer接口动态开启国标收流端口后,这个端口只能产生一个流,也就是说,一个摄像头需要一个服务器端口用于接收国标推流。
+- 以下是演示范例(postman 工具调用 openRtpServer 接口创建随机端口):
-- 以下是演示范例(postman工具调用openRtpServer接口创建随机端口):
+![图片](https://user-images.githubusercontent.com/11495632/93871851-e232dc00-fd01-11ea-8802-b8e91e5f6de1.png =1631x)
-
+- 然后启动 FFmpeg 推流
-- 然后启动FFmpeg推流
```bash
ffmpeg -re -i www/record/robot.mp4 -vcodec h264 -acodec aac -f rtp_mpegts rtp://127.0.0.1:50077
```
- 以下是推流后注册的服务器日志
-![图片](/images/gb28181_push_streaming_2.png)
-
-- 需要指出的是,如果openRtpServer接口创建的端口一直没收到流(或者解析不出流),那么会自动关闭和释放。
+ ![图片](/images/gb28181_push_streaming_2.png)
+- 需要指出的是,如果 openRtpServer 接口创建的端口一直没收到流(或者解析不出流),那么会自动关闭和释放。
## 调试文件生成
-如果你的MediaServer能收到国标推流,但是未出现`媒体注册`相关日志,那么有可能是流有些异常,你可以修改配置文件`rtp_proxy.dumpDir`指定调试文件导出目录,
-这样ZLMediaKit会把国标流导出到该文件夹,就像这样:
-
+如果你的 MediaServer 能收到国标推流,但是未出现`媒体注册`相关日志,那么有可能是流有些异常,你可以修改配置文件`rtp_proxy.dumpDir`指定调试文件导出目录,
+这样 ZLMediaKit 会把国标流导出到该文件夹,就像这样:
-你可以直接用ffplay播放`mp2/video后缀的文件`,`rtp`后缀的文件,你可以用测试工具`test_rtp`调试,或者你可以把它分享给其他人帮你分析原因。
+![图片](https://user-images.githubusercontent.com/11495632/93872911-6c2f7480-fd03-11ea-85d4-911d6d998c83.png =631x)
+你可以直接用 ffplay 播放`mp2/video后缀的文件`,`rtp`后缀的文件,你可以用测试工具`test_rtp`调试,或者你可以把它分享给其他人帮你分析原因。
-## 让ZLMediaKit往其他国标服务器推流
-你可以使用[restful api](../../media_server/restful_api.md#27indexapistartsendrtp)让ZLMediaKit生成国标流并往其他服务器推送,支持其他任何已注册的流转国标流。
+## 让 ZLMediaKit 往其他国标服务器推流
-- postman调用startSendRtp接口推送国标流:
+你可以使用[restful api](../../media_server/restful_api.md#27indexapistartsendrtp)让 ZLMediaKit 生成国标流并往其他服务器推送,支持其他任何已注册的流转国标流。
-
+- postman 调用 startSendRtp 接口推送国标流:
-![图片](/images/gb28181_push_streaming_3.png)
+![图片](https://user-images.githubusercontent.com/11495632/93873636-a0576500-fd04-11ea-8b0f-98fb3f60c778.png =1551x)
+![图片](/images/gb28181_push_streaming_3.png)
-- 上图中是推送国标流给自己,当然你也可以推送给其他服务器,支持udp/tcp方式推流。
+- 上图中是推送国标流给自己,当然你也可以推送给其他服务器,支持 udp/tcp 方式推流。
## 性能
-GB28181的推流性能测试,请参考:[#961](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
+
+GB28181 的推流性能测试,请参考:[#961](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
## 丢包问题调试
-如果在测试GB28181 UDP推流时,频繁打印以下日志:
+
+如果在测试 GB28181 UDP 推流时,频繁打印以下日志:
![图片](/images/gb28181_push_streaming_4.png)
-请查看此[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/1221),特别提示,wifi情况下,由于无线网络干扰严重,丢包问题很可能确实是网络质量差导致的。
+请查看此[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/1221),特别提示,wifi 情况下,由于无线网络干扰严重,丢包问题很可能确实是网络质量差导致的。
## 相关文章推荐阅读
-[WVP+ZLMediaKit+MediaServerUI实现摄像头GB28181推流播放录制 ](https://notemi.cn/wvp---zlmedia-kit---mediaserverui-to-realize-streaming-playback-and-recording-of-camera-gb28181.html)
-[使用 GB28181.Solution + ZLMediaKit + MediaServerUI 进行摄像头推流和播放](http://dlgcy.com/gb28181-solution-zlmediakit-mediaserverui/)
+[WVP+ZLMediaKit+MediaServerUI 实现摄像头 GB28181 推流播放录制](https://notemi.cn/wvp---zlmedia-kit---mediaserverui-to-realize-streaming-playback-and-recording-of-camera-gb28181.html)
-[GB28181语音对讲](https://github.com/ZLMediaKit/ZLMediaKit/issues/2217)
+[使用 GB28181.Solution + ZLMediaKit + MediaServerUI 进行摄像头推流和播放](http://dlgcy.com/gb28181-solution-zlmediakit-mediaserverui/)
+[GB28181 语音对讲](https://github.com/ZLMediaKit/ZLMediaKit/issues/2217)
diff --git a/src/zh/guide/protocol/srt/README.md b/src/zh/guide/protocol/srt/README.md
index 96c3b2b..7e64c8c 100644
--- a/src/zh/guide/protocol/srt/README.md
+++ b/src/zh/guide/protocol/srt/README.md
@@ -3,50 +3,53 @@ title: SRT
---
## 特性
+
- NACK(重传)
- listener 支持
-- 推流只支持ts推流
-- 拉流只支持ts拉流
+- 推流只支持 ts 推流
+- 拉流只支持 ts 拉流
- 协议实现 [参考](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html)
- 版本支持(>=1.3.0)
-- fec与加密没有实现
+- fec 与加密没有实现
## 使用
-zlm中的srt根据streamid 来确定是推流还是拉流,来确定vhost,app,streamid(ZLM中的)、
+zlm 中的 srt 根据 streamid 来确定是推流还是拉流,来确定 vhost,app,streamid(ZLM 中的)、
-srt中的streamid 为 `#!::key1=value1,key2=value2,key3=value4......`
+srt 中的 streamid 为 `#!::key1=value1,key2=value2,key3=value4......`
-h,r为特殊的key,来确定vhost,app,streamid,如果没有h则vhost为默认值
+h,r 为特殊的 key,来确定 vhost,app,streamid,如果没有 h 则 vhost 为默认值
-m 为特殊key来确定是推流还是拉流,如果为publish 则为推流,否则为拉流 ,如果不存在m,则默认为拉流
+m 为特殊 key 来确定是推流还是拉流,如果为 publish 则为推流,否则为拉流 ,如果不存在 m,则默认为拉流
-其他key与m会作为webhook的鉴权参数
+其他 key 与 m 会作为 webhook 的鉴权参数
如:
- #!::h=zlmediakit.com,r=live/test,m=publish
- vhost = zlmediakit.com
+```
+#!::h=zlmediakit.com,r=live/test,m=publish
- app = live
+vhost = zlmediakit.com
- streamid = test
+app = live
- 是推流
+streamid = test
+```
+是推流
- OBS 推流地址
- `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
+ `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
+
- ffmpeg 推流
- `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
+ `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish`
+
- ffplay 拉流
- `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test`
+ `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test`
- vlc 拉流
- - vlc拉流需要在偏好设置->串流输出->访问输出->SRT中设置streamid,例如`#!::r=live/test`
- - 拉流时只需填入`srt://192.168.1.105:9000`即可
-
-
+ - vlc 拉流需要在偏好设置->串流输出->访问输出->SRT 中设置 streamid,例如`#!::r=live/test`
+ - 拉流时只需填入`srt://192.168.1.105:9000`即可
diff --git a/src/zh/guide/protocol/webrtc/webrtc_compilation_and_use.md b/src/zh/guide/protocol/webrtc/webrtc_compilation_and_use.md
index 4f8cab4..1c91f98 100644
--- a/src/zh/guide/protocol/webrtc/webrtc_compilation_and_use.md
+++ b/src/zh/guide/protocol/webrtc/webrtc_compilation_and_use.md
@@ -13,76 +13,80 @@ cmake version 3.20.5
## 依赖准备
-- openssl 安装 (openssl版本要求1.1以上)
-
- ```shell
- $ wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
- $ tar -xvzf openssl-1.1.1k.tar.gz
- $ yum install -y zlib zlib-devel perl-CPAN
- $ ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl
- $ make && make install
- $ echo "/usr/local/lib64/" >> /etc/ld.so.conf
- $ echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
- $ ldconfig
- $ ln -s /usr/local/openssl/bin/openssl /usr/local/bin/openssl # 替换系统openssl,非必须
- $ openssl version -a
- ```
-
-- libsrtp安装
-
- 点击[这里](https://codeload.github.com/cisco/libsrtp/tar.gz/refs/tags/v2.3.0)下载安装
-
- ```shell
- $ tar -xvzf libsrtp-2.3.0.tar.gz
- $ cd libsrtp-2.3.0
- $ ./configure --enable-openssl --with-openssl-dir=/usr/local/openssl
- $ make -j8 && make install
- ```
-
- 对于一些比较新的编译环境(如GCC 10+),编译 libsrtp-2.3.0 可能会存在问题,可以考虑切换到 2.5.0 版本,即
- ```
- $ wget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz
- $ tar -xvzf libsrtp-2.5.0.tar.gz
- $ cd libsrtp-2.5.0
- ```
+- openssl 安装 (openssl 版本要求 1.1 以上)
+
+ ```shell
+ $ wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
+ $ tar -xvzf openssl-1.1.1k.tar.gz
+ $ yum install -y zlib zlib-devel perl-CPAN
+ $ ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl
+ $ make && make install
+ $ echo "/usr/local/lib64/" >> /etc/ld.so.conf
+ $ echo "/usr/local/openssl/lib" >> /etc/ld.so.conf
+ $ ldconfig
+ $ ln -s /usr/local/openssl/bin/openssl /usr/local/bin/openssl # 替换系统openssl,非必须
+ $ openssl version -a
+ ```
+
+- libsrtp 安装
+
+ 点击[这里](https://codeload.github.com/cisco/libsrtp/tar.gz/refs/tags/v2.3.0)下载安装
+
+ ```shell
+ $ tar -xvzf libsrtp-2.3.0.tar.gz
+ $ cd libsrtp-2.3.0
+ $ ./configure --enable-openssl --with-openssl-dir=/usr/local/openssl
+ $ make -j8 && make install
+ ```
+
+ 对于一些比较新的编译环境(如 GCC 10+),编译 libsrtp-2.3.0 可能会存在问题,可以考虑切换到 2.5.0 版本,即
+
+ ```sh
+ $ wget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz
+ $ tar -xvzf libsrtp-2.5.0.tar.gz
+ $ cd libsrtp-2.5.0
+ ```
## 编译
-- 下载zlm源码
+- 下载 zlm 源码
- ```shell
- #国内用户推荐从同步镜像网站gitee下载
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- #千万不要忘记执行这句命令
- git submodule update --init
- ```
+ ```shell
+ #国内用户推荐从同步镜像网站gitee下载
+ git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+ cd ZLMediaKit
+ #千万不要忘记执行这句命令
+ git submodule update --init
+ ```
- 编译
- ```shell
- $ mkdir build
- $ cd build
- $ cmake .. -DENABLE_WEBRTC=true -DOPENSSL_ROOT_DIR=/usr/local/openssl -DOPENSSL_LIBRARIES=/usr/local/openssl/lib
- $ cmake --build . --target MediaServer
-
- # 最终输出
- [ 96%] Built target test_rtcp_fci
- [ 96%] Building CXX object tests/CMakeFiles/test_rtp.dir/test_rtp.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_rtp
- [ 97%] Built target test_rtp
- [ 97%] Building CXX object tests/CMakeFiles/test_wsServer.dir/test_wsServer.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_wsServer
- [ 97%] Built target test_wsServer
- [ 97%] Building CXX object tests/CMakeFiles/test_server.dir/test_server.cpp.o
- [ 97%] Linking CXX executable ../../release/linux/Debug/test_server
- [ 97%] Built target test_server
- [ 98%] Built target jsoncpp
- [ 98%] Linking CXX executable ../../release/linux/Debug/MediaServer
- [100%] Built target MediaServer
- ```
+ ```shell
+ $ mkdir build
+ $ cd build
+ $ cmake .. -DENABLE_WEBRTC=true -DOPENSSL_ROOT_DIR=/usr/local/openssl -DOPENSSL_LIBRARIES=/usr/local/openssl/lib
+ $ cmake --build . --target MediaServer
+
+ # 最终输出
+ [ 96%] Built target test_rtcp_fci
+ [ 96%] Building CXX object tests/CMakeFiles/test_rtp.dir/test_rtp.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_rtp
+ [ 97%] Built target test_rtp
+ [ 97%] Building CXX object tests/CMakeFiles/test_wsServer.dir/test_wsServer.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_wsServer
+ [ 97%] Built target test_wsServer
+ [ 97%] Building CXX object tests/CMakeFiles/test_server.dir/test_server.cpp.o
+ [ 97%] Linking CXX executable ../../release/linux/Debug/test_server
+ [ 97%] Built target test_server
+ [ 98%] Built target jsoncpp
+ [ 98%] Linking CXX executable ../../release/linux/Debug/MediaServer
+ [100%] Built target MediaServer
+ ```
+
## 修改配置文件
-由于webrtc协议需要告知播放器服务器所在ip,如果该ip对播放器不可见,会导致webrtc无法联通。请修改配置文件中`rtc.externIP`为播放器可见ip,如果不设置该配置项,zlmediakit将获取网卡ip(一般是内网ip),那么将无法跨域nat使用webrtc。
+
+由于 webrtc 协议需要告知播放器服务器所在 ip,如果该 ip 对播放器不可见,会导致 webrtc 无法联通。请修改配置文件中`rtc.externIP`为播放器可见 ip,如果不设置该配置项,zlmediakit 将获取网卡 ip(一般是内网 ip),那么将无法跨域 nat 使用 webrtc。
+
```ini
[rtc]
#rtc播放推流、播放超时时间
@@ -99,36 +103,38 @@ rembBitRate=1000000
## 测试
-最新的zlmediakit源码自带有效的ssl证书`default.pem`,对应的域名是`default.zlmediakit.com`,该域名解析到的ip为`127.0.0.1`,用户在浏览器中打开 [https://default.zlmediakit.com/webrtc/](https://default.zlmediakit.com/webrtc/)即可开始测试。请先推流后,再测试播放。如果webrtc无法播放,
+最新的 zlmediakit 源码自带有效的 ssl 证书`default.pem`,对应的域名是`default.zlmediakit.com`,该域名解析到的 ip 为`127.0.0.1`,用户在浏览器中打开 [https://default.zlmediakit.com/webrtc/](https://default.zlmediakit.com/webrtc/)即可开始测试。请先推流后,再测试播放。如果 webrtc 无法播放,
请参考此[issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/1277)
## 问题解决
- 提示 `gmake[3]: *** No rule to make target `/usr/lib64/libssl.so', needed by `../release/linux/Debug/MediaServer'. Stop.`
- ```
- cd /usr/local/openssl/lib
- cp -r ./* /usr/lib64/
- ```
-- ubuntu编译
+ ```sh
+ cd /usr/local/openssl/lib
+ cp -r ./* /usr/lib64/
+ ```
+
+- ubuntu 编译
可以参考网友大神自制[这里](https://blog.csdn.net/haysonzeng/article/details/116754065)
-- windows编译
+- windows 编译
可以参考网友大神自制[这里](https://blog.csdn.net/byna11sina11/article/details/119786889)
还有[这里](https://github.com/ZLMediaKit/ZLMediaKit/issues/1081#issuecomment-910141630)
+
## Q And A(播放问题) ?
+
- obs 推流 rtc 播放一卡一卡?
- web的rtc h264 不支持B帧,需要去掉B帧, 使用FFmpeg时需要添加`-bf 0`参数,或者指定h264 profile为baseline
+ web 的 rtc h264 不支持 B 帧,需要去掉 B 帧, 使用 FFmpeg 时需要添加`-bf 0`参数,或者指定 h264 profile 为 baseline
- rtsp 推流,rtc 播放不成功?
- rtsp 推流需要把zlm的配置文件中的directProxy 设置为0
+ rtsp 推流需要把 zlm 的配置文件中的 directProxy 设置为 0
- webrtc 视频或者音频播放不出来?
- web客户端的rtc 支持h264,opus/48000/2,pcma/8000,pcmu/8000等编码格式,检查一下编码格式是否正确,一般都是音频不支持,需要使用transcode 分支来转码(视频不会转码)
-
+ web 客户端的 rtc 支持 h264,opus/48000/2,pcma/8000,pcmu/8000 等编码格式,检查一下编码格式是否正确,一般都是音频不支持,需要使用 transcode 分支来转码(视频不会转码)
diff --git a/src/zh/guide/protocol/webrtc/webrtc_signaling_interaction_format.md b/src/zh/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
index f702130..23eecb6 100644
--- a/src/zh/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
+++ b/src/zh/guide/protocol/webrtc/webrtc_signaling_interaction_format.md
@@ -1,8 +1,10 @@
---
title: webrtc信令交互格式
---
+
## 前言
-zlmediakit webrtc信令格式新增支持whip/whep标准,测试地址如下:
+
+zlmediakit webrtc 信令格式新增支持 whip/whep 标准,测试地址如下:
推流:https://zlmediakit.com/index/api/whip?app=live&stream=test
@@ -10,29 +12,33 @@ zlmediakit webrtc信令格式新增支持whip/whep标准,测试地址如下:
本文后续篇幅为私有信令格式。
-## 一、webrtc sdp交换请求基本格式
+## 一、webrtc sdp 交换请求基本格式
- 请求地址: /index/api/webrtc?app=live&stream=test&type=[push/play/echo]
- 请求方式: http post
-- 请求body: webrtc offer sdp
-- 回复body:
+- 请求 body: webrtc offer sdp
+- 回复 body:
+
```json
{
- "code" : 0,
- "id" : "zlm_1",
- "sdp" : "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
- "type" : "answer"
+ "code": 0,
+ "id": "zlm_1",
+ "sdp": "v=0\r\no=mozilla...THIS_IS_SDPARTA-99.0 6880954646154322397 0 IN IP4 172.18.190.185\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0 1\r\na=msid-semantic: WMS *\r\na=ice-lite\r\nm=audio 8000 UDP/TLS/RTP/SAVPF 0\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:0\r\na=ice-lite\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2/sendonly urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:0 PCMU/8000/1\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\nm=video 8000 UDP/TLS/RTP/SAVPF 126 127\r\nc=IN IP4 172.18.190.185\r\na=rtcp:8000 IN IP4 172.18.190.185\r\na=ice-ufrag:rBK+uR9AAAA=_2\r\na=ice-pwd:H4rtFC1xhef0ynU2lk8z22ha\r\na=fingerprint:sha-256 6E:EF:E7:75:56:2A:66:DF:6C:9D:72:B6:A5:21:35:73:19:66:D8:00:F4:BC:36:59:61:1B:5D:35:13:99:14:AE\r\na=setup:passive\r\na=mid:1\r\na=ice-lite\r\na=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:5 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:6/sendonly http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\r\na=extmap:7 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=recvonly\r\na=rtcp-mux\r\na=rtpmap:126 H264/90000\r\na=rtcp-fb:126 ccm fir\r\na=rtcp-fb:126 goog-remb\r\na=rtcp-fb:126 nack\r\na=rtcp-fb:126 nack pli\r\na=rtcp-fb:126 transport-cc\r\na=fmtp:126 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f;x-google-max-bitrate=8000;x-google-min-bitrate=4000;x-google-start-bitrate=6000\r\na=rtpmap:127 rtx/90000\r\na=fmtp:127 apt=126\r\na=candidate:udpcandidate 1 udp 120 172.18.190.185 8000 typ host\r\n",
+ "type": "answer"
}
```
-## 二、支持的type类型
-- push: webrtc推流
-- play: webrtc播放
-- echo: webrtc镜像回显(仅用于webrtc双向测试)
+## 二、支持的 type 类型
+
+- push: webrtc 推流
+- play: webrtc 播放
+- echo: webrtc 镜像回显(仅用于 webrtc 双向测试)
- 用户可以二次开发注册更多类型插件。
## 三、范例
+
- 请求:
+
```http
POST /index/api/webrtc?app=live&stream=test&type=push HTTP/1.1
Host: 127.0.0.1:8080
@@ -135,6 +141,7 @@ a=ssrc-group:FID 3676200744 3937745592
```
- 响应:
+
```http
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
@@ -154,6 +161,3 @@ Server: ZLMediaKit(git hash:500d2c6a/2023-03-14T17:33:46+08:00,branch:master,bui
}
```
-
-
-
diff --git a/src/zh/guide/sdk/README.md b/src/zh/guide/sdk/README.md
index f8ab26e..3f77a4d 100644
--- a/src/zh/guide/sdk/README.md
+++ b/src/zh/guide/sdk/README.md
@@ -4,6 +4,4 @@ icon: cube
index: false
---
-## Introduction
-
-We support foo feature, ...
+
diff --git a/src/zh/more/collaborative_projects.md b/src/zh/more/collaborative_projects.md
index 05c7d0c..ac0d8d0 100644
--- a/src/zh/more/collaborative_projects.md
+++ b/src/zh/more/collaborative_projects.md
@@ -3,32 +3,37 @@ title: 合作项目
icon: circle-info
---
- - 视频管理平台
- - [wvp-GB28181-pro](https://github.com/648540858/wvp-GB28181-pro) java实现的开箱即用的GB28181协议视频平台
- - [AKStream](https://github.com/chatop2020/AKStream) c#实现的全功能的软NVR接口/GB28181平台
- - [BXC_SipServer](https://github.com/any12345com/BXC_SipServer) c++实现的国标GB28181流媒体信令服务器
- - [gosip](https://github.com/panjjo/gosip) golang实现的GB28181服务器
- - [FreeEhome](https://github.com/tsingeye/FreeEhome) golang实现的海康ehome服务器
-
- - 播放器
- - [h265web.js](https://github.com/numberwolf/h265web.js) 基于wasm支持H265的播放器,支持本项目多种专属协议
- - [jessibuca](https://github.com/langhuihui/jessibuca) 基于wasm支持H265的播放器
- - [wsPlayer](https://github.com/v354412101/wsPlayer) 基于MSE的websocket-fmp4播放器
- - [BXC_gb28181Player](https://github.com/any12345com/BXC_gb28181Player) C++开发的支持国标GB28181协议的视频流播放器
-
-- WEB管理网站
- - [zlm_webassist](https://github.com/1002victor/zlm_webassist) 本项目配套的前后端分离web管理项目
- - [AKStreamNVR](https://github.com/langmansh/AKStreamNVR) 前后端分离web项目,支持webrtc播放
-
- - SDK
- - [c# sdk](https://github.com/malegend/ZLMediaKit.Autogen) 本项目c sdk完整c#包装库
- - [metaRTC](https://github.com/metartc/metaRTC) 全国产纯c webrtc sdk
-
- - 其他项目(已停止更新)
- - [NodeJS实现的GB28181平台](https://gitee.com/hfwudao/GB28181_Node_Http)
- - [基于ZLMediaKit主线的管理WEB网站 ](https://gitee.com/kkkkk5G/MediaServerUI)
- - [基于ZLMediaKit分支的管理WEB网站](https://github.com/chenxiaolei/ZLMediaKit_NVR_UI)
- - [一个非常漂亮的可视化后台管理系统](https://github.com/MingZhuLiu/ZLMediaServerManagent)
- - [基于C SDK实现的推流客户端](https://github.com/hctym1995/ZLM_ApiDemo)
- - [C#版本的Http API与Hook](https://github.com/chengxiaosheng/ZLMediaKit.HttpApi)
- - [DotNetCore的RESTful客户端](https://github.com/MingZhuLiu/ZLMediaKit.DotNetCore.Sdk)
+- 视频管理平台
+
+ - [wvp-GB28181-pro](https://github.com/648540858/wvp-GB28181-pro) java 实现的开箱即用的 GB28181 协议视频平台
+ - [AKStream](https://github.com/chatop2020/AKStream) c#实现的全功能的软 NVR 接口/GB28181 平台
+ - [BXC_SipServer](https://github.com/any12345com/BXC_SipServer) c++实现的国标 GB28181 流媒体信令服务器
+ - [gosip](https://github.com/panjjo/gosip) golang 实现的 GB28181 服务器
+ - [FreeEhome](https://github.com/tsingeye/FreeEhome) golang 实现的海康 ehome 服务器
+
+- 播放器
+
+ - [h265web.js](https://github.com/numberwolf/h265web.js) 基于 wasm 支持 H265 的播放器,支持本项目多种专属协议
+ - [jessibuca](https://github.com/langhuihui/jessibuca) 基于 wasm 支持 H265 的播放器
+ - [wsPlayer](https://github.com/v354412101/wsPlayer) 基于 MSE 的 websocket-fmp4 播放器
+ - [BXC_gb28181Player](https://github.com/any12345com/BXC_gb28181Player) C++开发的支持国标 GB28181 协议的视频流播放器
+
+- WEB 管理网站
+
+ - [zlm_webassist](https://github.com/1002victor/zlm_webassist) 本项目配套的前后端分离 web 管理项目
+ - [AKStreamNVR](https://github.com/langmansh/AKStreamNVR) 前后端分离 web 项目,支持 webrtc 播放
+
+- SDK
+
+ - [c# sdk](https://github.com/malegend/ZLMediaKit.Autogen) 本项目 c sdk 完整 c#包装库
+ - [metaRTC](https://github.com/metartc/metaRTC) 全国产纯 c webrtc sdk
+
+- 其他项目(已停止更新)
+
+ - [NodeJS 实现的 GB28181 平台](https://gitee.com/hfwudao/GB28181_Node_Http)
+ - [基于 ZLMediaKit 主线的管理 WEB 网站 ](https://gitee.com/kkkkk5G/MediaServerUI)
+ - [基于 ZLMediaKit 分支的管理 WEB 网站](https://github.com/chenxiaolei/ZLMediaKit_NVR_UI)
+ - [一个非常漂亮的可视化后台管理系统](https://github.com/MingZhuLiu/ZLMediaServerManagent)
+ - [基于 C SDK 实现的推流客户端](https://github.com/hctym1995/ZLM_ApiDemo)
+ - [C#版本的 Http API 与 Hook](https://github.com/chengxiaosheng/ZLMediaKit.HttpApi)
+ - [DotNetCore 的 RESTful 客户端](https://github.com/MingZhuLiu/ZLMediaKit.DotNetCore.Sdk)
diff --git a/src/zh/more/contact.md b/src/zh/more/contact.md
index 14dc52d..d213f4d 100644
--- a/src/zh/more/contact.md
+++ b/src/zh/more/contact.md
@@ -5,9 +5,11 @@ icon: circle-info
## 联系信息
- - 邮箱:<1213642868@qq.com>(本项目相关或流媒体相关问题请走issue流程,否则恕不邮件答复)
- - 请关注微信公众号获取最新消息推送:
-
-
- - 也可以自愿有偿加入知识星球咨询和获取资料:
-
+- 邮箱:<1213642868@qq.com>(本项目相关或流媒体相关问题请走 issue 流程,否则恕不邮件答复)
+- 请关注微信公众号获取最新消息推送:
+
+ ![图片](https://user-images.githubusercontent.com/11495632/232451702-4c50bc72-84d8-4c94-af2b-57290088ba7a.png =200x)
+
+- 也可以自愿有偿加入知识星球咨询和获取资料:
+
+ ![图片](https://user-images.githubusercontent.com/11495632/231946329-aa8517b0-3cf5-49cf-8c75-a93ed58cb9d2.png =200x)
diff --git a/src/zh/more/license.md b/src/zh/more/license.md
index 295bedc..081c629 100644
--- a/src/zh/more/license.md
+++ b/src/zh/more/license.md
@@ -3,7 +3,7 @@ title: 授权协议
icon: circle-info
---
-本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。
+本项目自有代码使用宽松的 MIT 协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。
但是本项目也零碎的使用了一些其他的[开源代码](../reference/resources/dependency.md),在商用的情况下请自行替代或剔除;
由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。
在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议。
diff --git a/src/zh/more/thanks.md b/src/zh/more/thanks.md
index 93478b5..af86838 100644
--- a/src/zh/more/thanks.md
+++ b/src/zh/more/thanks.md
@@ -2,13 +2,13 @@
title: 致谢
icon: circle-info
---
+
## 特别感谢
本项目采用了[老陈](https://github.com/ireader) 的 [media-server](https://github.com/ireader/media-server) 库,
-本项目的 ts/fmp4/mp4/ps 容器格式的复用解复用都依赖media-server库。在实现本项目诸多功能时,老陈多次给予了无私热情关键的帮助,
+本项目的 ts/fmp4/mp4/ps 容器格式的复用解复用都依赖 media-server 库。在实现本项目诸多功能时,老陈多次给予了无私热情关键的帮助,
特此对他表示诚挚的感谢!
-
## 致谢
感谢以下各位对本项目包括但不限于代码贡献、问题反馈、资金捐赠等各种方式的支持!以下排名不分先后:
@@ -24,7 +24,7 @@ icon: circle-info
[DroidChow](https://github.com/DroidChow)
[阿塞](https://github.com/HuoQiShuai)
[火宣](https://github.com/ChinaCCF)
-[γ瑞γミ](https://github.com/JerryLinGd)
+[γ 瑞 γ ミ](https://github.com/JerryLinGd)
[linkingvision](https://www.linkingvision.com/)
[茄子](https://github.com/taotaobujue2008)
[好心情](mailto:409257224@qq.com)
@@ -112,7 +112,6 @@ icon: circle-info
[leibnewton](https://github.com/leibnewton)
[1002victor](https://github.com/1002victor)
-同时感谢JetBrains对开源项目的支持,本项目使用CLion开发与调试:
+同时感谢 JetBrains 对开源项目的支持,本项目使用 CLion 开发与调试:
[![JetBrains](https://resources.jetbrains.com/storage/products/company/brand/logos/CLion.svg)](https://jb.gg/OpenSourceSupport)
-
diff --git a/src/zh/more/use_cases.md b/src/zh/more/use_cases.md
index ece744b..9f914a8 100644
--- a/src/zh/more/use_cases.md
+++ b/src/zh/more/use_cases.md
@@ -4,5 +4,5 @@ icon: circle-info
---
本项目已经得到不少公司和个人开发者的认可,据作者不完全统计,
-使用本项目的公司包括知名的互联网巨头、国内排名前列的云服务公司、多家知名的AI独角兽公司,
+使用本项目的公司包括知名的互联网巨头、国内排名前列的云服务公司、多家知名的 AI 独角兽公司,
以及一系列中小型公司。使用者可以通过在 [issue](https://github.com/ZLMediaKit/ZLMediaKit/issues/511) 上粘贴公司的大名和相关项目介绍为本项目背书,感谢支持!
diff --git a/src/zh/reference/development_log/hls_high_performance_journey.md b/src/zh/reference/development_log/hls_high_performance_journey.md
index 5ec4798..f5167cb 100644
--- a/src/zh/reference/development_log/hls_high_performance_journey.md
+++ b/src/zh/reference/development_log/hls_high_performance_journey.md
@@ -4,30 +4,32 @@ title: zlmediakit的hls高性能之旅
## 事情的起因
-北京冬奥会前夕,zlmediakit的一位用户完成了iptv系统的迁移; 由于zlmediakit对hls的支持比较完善,支持包括鉴权、统计、溯源等独家特性,所以他把之前的老系统都迁移到zlmediakit上了。
+北京冬奥会前夕,zlmediakit 的一位用户完成了 iptv 系统的迁移; 由于 zlmediakit 对 hls 的支持比较完善,支持包括鉴权、统计、溯源等独家特性,所以他把之前的老系统都迁移到 zlmediakit 上了。
-但是很不幸,在冬奥会开幕式当天,zlmediakit并没有承受起考验,当hls并发数达到3000左右时,zlmediakit线程负载接近100%,延时非常高,整个服务器基本不可用:
+但是很不幸,在冬奥会开幕式当天,zlmediakit 并没有承受起考验,当 hls 并发数达到 3000 左右时,zlmediakit 线程负载接近 100%,延时非常高,整个服务器基本不可用:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-8d6b45ad1518b2b2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/320)
## 思考
-zlmediakit定位是一个通用的流媒体服务器,主要精力聚焦在rtsp/rtmp等协议,对hls的优化并不够重视,hls之前在zlmediakit里面实现方式跟http文件服务器实现方式基本一致,都是通过直接读取文件的方式提供下载。所以当hls播放数比较高时,每个用户播放都需要重新从磁盘读取一遍文件,这时文件io承压,由于磁盘慢速度的特性,不能承载太高的并发数。
-有些朋友可能会问,如果用内存虚拟磁盘能不能提高性能?答案是能,但是由于内存拷贝带宽也存在上限,所以就算hls文件都放在内存目录,每次读取文件也会存在多次memcopy,性能并不能有太大的飞跃。前面冬奥会直播事故那个案例,就是把hls文件放在内存目录,但是也就能承载2000+并发而已。
+zlmediakit 定位是一个通用的流媒体服务器,主要精力聚焦在 rtsp/rtmp 等协议,对 hls 的优化并不够重视,hls 之前在 zlmediakit 里面实现方式跟 http 文件服务器实现方式基本一致,都是通过直接读取文件的方式提供下载。所以当 hls 播放数比较高时,每个用户播放都需要重新从磁盘读取一遍文件,这时文件 io 承压,由于磁盘慢速度的特性,不能承载太高的并发数。
+有些朋友可能会问,如果用内存虚拟磁盘能不能提高性能?答案是能,但是由于内存拷贝带宽也存在上限,所以就算 hls 文件都放在内存目录,每次读取文件也会存在多次 memcopy,性能并不能有太大的飞跃。前面冬奥会直播事故那个案例,就是把 hls 文件放在内存目录,但是也就能承载 2000+并发而已。
## 歧途: sendfile
-为了解决hls并发瓶颈这个问题,我首先思考到的是`sendfile`方案。我们知道,`nginx`作为http服务器的标杆,就支持sendfile这个特性。很早之前,我就听说过`sendfile`多牛逼,它支持直接把文件发送到`socket fd`;而不用通过用户态和内核态的内存互相拷贝,可以大幅提高文件发送的性能。
-我们查看sendfile的资料,有如下介绍:
+为了解决 hls 并发瓶颈这个问题,我首先思考到的是`sendfile`方案。我们知道,`nginx`作为 http 服务器的标杆,就支持 sendfile 这个特性。很早之前,我就听说过`sendfile`多牛逼,它支持直接把文件发送到`socket fd`;而不用通过用户态和内核态的内存互相拷贝,可以大幅提高文件发送的性能。
+
+我们查看 sendfile 的资料,有如下介绍:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-74226856ef85a257.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-于是,在事故反馈当日,2022年春节期间的某天深夜,我在严寒之下光着膀子在zlmediakit中把sendfile特性实现了一遍:
+于是,在事故反馈当日,2022 年春节期间的某天深夜,我在严寒之下光着膀子在 zlmediakit 中把 sendfile 特性实现了一遍:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-512ca5a1ebd6c0dc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
实现的代码如下:
-```c++
+
+```cpp
//HttpFileBody.cpp
int HttpFileBody::sendFile(int fd) {
#if defined(__linux__) || defined(__linux)
@@ -64,37 +66,37 @@ void HttpSession::sendResponse(int code,
}
```
-由于sendfile只能直接发送文件明文内容,所以并不适用于需要文件加密的https场景;这个优化,https是无法开启的;很遗憾,这次hls事故中,用户恰恰用的就是https-hls。所以本次优化并没起到实质作用(https时关闭sendfile特性是在用户反馈tls解析异常才加上的)。
+由于 sendfile 只能直接发送文件明文内容,所以并不适用于需要文件加密的 https 场景;这个优化,https 是无法开启的;很遗憾,这次 hls 事故中,用户恰恰用的就是 https-hls。所以本次优化并没起到实质作用(https 时关闭 sendfile 特性是在用户反馈 tls 解析异常才加上的)。
-## 优化之旅一:共享mmap
+## 优化之旅一:共享 mmap
-很早之前,zlmediakit已经支持mmap方式发送文件了,但是在本次hls直播事故中,并没有发挥太大的作用,原因有以下几点:
+很早之前,zlmediakit 已经支持 mmap 方式发送文件了,但是在本次 hls 直播事故中,并没有发挥太大的作用,原因有以下几点:
-- 1.每个hls播放器访问的ts文件都是独立的,每访问一次都需要建立一次mmap映射,这样导致其实每次都需要内存从文件加载一次文件到内存,并没有减少磁盘io压力。
+- 1.每个 hls 播放器访问的 ts 文件都是独立的,每访问一次都需要建立一次 mmap 映射,这样导致其实每次都需要内存从文件加载一次文件到内存,并没有减少磁盘 io 压力。
-- 2.mmap映射次数太多,导致内存不足,mmap映射失败,则会回退为fread方式。
+- 2.mmap 映射次数太多,导致内存不足,mmap 映射失败,则会回退为 fread 方式。
-- 3.由于hls m3u8索引文件是会一直覆盖重写的,而mmap在文件长度发送变化时,会触发SIGBUS的错误,之前为了修复这个bug,在访问m3u8文件时,zlmediakit会强制采用fread方案。
+- 3.由于 hls m3u8 索引文件是会一直覆盖重写的,而 mmap 在文件长度发送变化时,会触发 SIGBUS 的错误,之前为了修复这个 bug,在访问 m3u8 文件时,zlmediakit 会强制采用 fread 方案。
-于是在sendfile优化方案失败时,我想到了共享mmap方案,其优化思路如下:
+于是在 sendfile 优化方案失败时,我想到了共享 mmap 方案,其优化思路如下:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-7f703110baa254c5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-共享mmap方案主要解决以下几个问题:
+共享 mmap 方案主要解决以下几个问题:
-- 防止文件多次mmap时被多次加载到内存,降低文件io压力。
+- 防止文件多次 mmap 时被多次加载到内存,降低文件 io 压力。
-- 防止mmap次数太多,导致mmap失败回退到fread方式。
+- 防止 mmap 次数太多,导致 mmap 失败回退到 fread 方式。
-- mmap映射内存在http明文传输情况下,直接写socket时不用经过内核用户态间的互相拷贝,可以降低内存带宽压力。
+- mmap 映射内存在 http 明文传输情况下,直接写 socket 时不用经过内核用户态间的互相拷贝,可以降低内存带宽压力。
于是大概在几天后,我新增了该特性:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4c1c70521321a923.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-实现代码逻辑其实比较简单,同时也比较巧妙,通过弱指针全局记录mmap实例,在无任何访问时,mmap自动回收,其代码如下:
+实现代码逻辑其实比较简单,同时也比较巧妙,通过弱指针全局记录 mmap 实例,在无任何访问时,mmap 自动回收,其代码如下:
-```c++
+```cpp
static std::shared_ptr getSharedMmap(const string &file_path, int64_t &file_size) {
{
lock_guard lck(s_mtx);
@@ -145,82 +147,85 @@ static std::shared_ptr getSharedMmap(const string &file_path, int64_t &fil
}
```
-通过本次优化,zlmediakit的hls服务有比较大的性能提升,性能上限大概提升到了6K左右(压测途中还发现拉流压测客户端由于mktime函数导致的性能瓶颈问题,在此不展开描述),但是还是离预期有些差距:
+通过本次优化,zlmediakit 的 hls 服务有比较大的性能提升,性能上限大概提升到了 6K 左右(压测途中还发现拉流压测客户端由于 mktime 函数导致的性能瓶颈问题,在此不展开描述),但是还是离预期有些差距:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9c7e706f317ea4c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
-> 小插曲: mktime函数导致拉流压测工具性能受限
+> 小插曲: mktime 函数导致拉流压测工具性能受限
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-d509266a091d97a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-## 优化之旅二:去除http cookie互斥锁
-在开启共享mmap后,发现性能上升到6K并发时,还是上不去;于是我登录服务器使用`gdb -p`调试进程,通过`info threads` 查看线程情况,发现大量线程处于阻塞状态,这也就是为什么zlmediakit占用cpu不高,但是并发却上不去的原因:
+## 优化之旅二:去除 http cookie 互斥锁
+
+在开启共享 mmap 后,发现性能上升到 6K 并发时,还是上不去;于是我登录服务器使用`gdb -p`调试进程,通过`info threads` 查看线程情况,发现大量线程处于阻塞状态,这也就是为什么 zlmediakit 占用 cpu 不高,但是并发却上不去的原因:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9b9db29311c8440a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-为什么这么多线程都处于互斥阻塞状态?zlmediakit在使用互斥锁时,还是比较注意缩小临界区的,一些复杂耗时的操作一般都会放在临界区之外;经过一番思索,我才恍然大悟,原因是:
+为什么这么多线程都处于互斥阻塞状态?zlmediakit 在使用互斥锁时,还是比较注意缩小临界区的,一些复杂耗时的操作一般都会放在临界区之外;经过一番思索,我才恍然大悟,原因是:
-> **压测客户端由于是单进程,共享同一份hls cookie,在访问zlmediakit时,这些分布在不同线程的请求,其cookie都相同,导致所有线程同时大规模操作同一个cookie,而操作cookie是要加锁的,于是这些线程疯狂的同时进行锁竞争,虽然不会死锁,但是会花费大量的时间用在锁等待上,导致整体性能降低。**
+> **压测客户端由于是单进程,共享同一份 hls cookie,在访问 zlmediakit 时,这些分布在不同线程的请求,其 cookie 都相同,导致所有线程同时大规模操作同一个 cookie,而操作 cookie 是要加锁的,于是这些线程疯狂的同时进行锁竞争,虽然不会死锁,但是会花费大量的时间用在锁等待上,导致整体性能降低。**
-虽然在真实使用场景下,用户cookie并不一致,这种几千用户同时访问同一个cookie的情况并不会存在,但是为了考虑不影响hls性能压测,也为了杜绝一切隐患,针对这个问题,我于是对http/hls的cookie机制进行了修改,在操作cookie时,不再上锁:
+虽然在真实使用场景下,用户 cookie 并不一致,这种几千用户同时访问同一个 cookie 的情况并不会存在,但是为了考虑不影响 hls 性能压测,也为了杜绝一切隐患,针对这个问题,我于是对 http/hls 的 cookie 机制进行了修改,在操作 cookie 时,不再上锁:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-ee5230a889b3891b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-348df864460eaefd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-之前对cookie上锁属于过度设计,当时目的主要是为了实现在cookie上随意挂载数据。
+之前对 cookie 上锁属于过度设计,当时目的主要是为了实现在 cookie 上随意挂载数据。
-## 优化之旅三:hls m3u8文件内存化
-经过上面两次优化,zlmediakit的hls并发能力可以达到8K了,但是当hls播放器个数达到在8K 左右时,zlmediakit的ts切片下载开始超时,可见系统还是存在性能瓶颈,联想到在优化cookie互斥锁时,有线程处于该状态:
+## 优化之旅三:hls m3u8 文件内存化
+
+经过上面两次优化,zlmediakit 的 hls 并发能力可以达到 8K 了,但是当 hls 播放器个数达到在 8K 左右时,zlmediakit 的 ts 切片下载开始超时,可见系统还是存在性能瓶颈,联想到在优化 cookie 互斥锁时,有线程处于该状态:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4c4cb2dd76e913ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
-所以我严重怀疑原因是m3u8文件不能使用mmap优化(而是采用fread方式)导致的文件io性能瓶颈问题,后面通过查看函数调用栈发现,果然是这个原因。
+所以我严重怀疑原因是 m3u8 文件不能使用 mmap 优化(而是采用 fread 方式)导致的文件 io 性能瓶颈问题,后面通过查看函数调用栈发现,果然是这个原因。
-由于m3u8是易变的,使用mmap映射时,如果文件长度发生变化,会导致触发SIGBUS的信号,查看多方资料,此问题无解。所以最后只剩下通过m3u8文件内存化来解决,于是我修好了m3u8文件的http下载方式,改成直接从内存获取:
+由于 m3u8 是易变的,使用 mmap 映射时,如果文件长度发生变化,会导致触发 SIGBUS 的信号,查看多方资料,此问题无解。所以最后只剩下通过 m3u8 文件内存化来解决,于是我修好了 m3u8 文件的 http 下载方式,改成直接从内存获取:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-175e50e0c1dbc104.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
## 结果:性能爆炸
-通过上述总共3大优化,我们在压测zlmediakit的hls性能时,随着一点一点增加并发量,发现zlmediakit总是能运行的非常健康,在并发量从10K慢慢增加到30K时,并不会影响ffplay播放的流畅性和效果,以下是压测数据:
-> 压测16K http-hls播放器时,流量大概7.5Gb/s:
-(大概需要32K端口,由于我测试机端口不足,只能最大压测到这个数据)
+通过上述总共 3 大优化,我们在压测 zlmediakit 的 hls 性能时,随着一点一点增加并发量,发现 zlmediakit 总是能运行的非常健康,在并发量从 10K 慢慢增加到 30K 时,并不会影响 ffplay 播放的流畅性和效果,以下是压测数据:
+
+> 压测 16K http-hls 播放器时,流量大概 7.5Gb/s:
+> (大概需要 32K 端口,由于我测试机端口不足,只能最大压测到这个数据)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-e4e50b03f39fb67a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-ac97bc4b78986289.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-2c64d8cd201ecd20.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-
-> 后面用户再压测了30k https-hls播放器:
+> 后面用户再压测了 30k https-hls 播放器:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-4f0ca1cb2f5df91c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-1569e4c146dd47b8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
-
## 后记:用户切生产环境
-在完成hls性能优化后,该用户把所有北美节点的hls流量切到了zlmediakit,
+
+在完成 hls 性能优化后,该用户把所有北美节点的 hls 流量切到了 zlmediakit,
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-10a6d17e6236fa48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-e6d38eda398a2b16.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/400)
## 状况又起:
-今天该用户又反馈给我说zlmediakit的内存占用非常高,在30K hls并发时,内存占用30+GB:
+
+今天该用户又反馈给我说 zlmediakit 的内存占用非常高,在 30K hls 并发时,内存占用 30+GB:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-577fd6cd88b3f0f3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
-但是用zlmediakit的`getThreadsLoad`接口查看,却发现负载很低:
+但是用 zlmediakit 的`getThreadsLoad`接口查看,却发现负载很低:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-9b200e5fb718781b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300)
-同时使用zlmediakit的`getStatistic`接口查看,发现`BufferList`对象个数很高,初步怀疑是由于网络带宽不足导致发送拥塞,内存暴涨,通过询问得知,公网hls访问,确实存在ts文件下载缓慢的问题:
+同时使用 zlmediakit 的`getStatistic`接口查看,发现`BufferList`对象个数很高,初步怀疑是由于网络带宽不足导致发送拥塞,内存暴涨,通过询问得知,公网 hls 访问,确实存在 ts 文件下载缓慢的问题:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-0259d17384210378.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-同时让他通过局域网测试ts下载,却发现非常快:
+同时让他通过局域网测试 ts 下载,却发现非常快:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-368e718cc2870cc8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-后来通过计算,发现确实由于网络带宽瓶颈每个用户积压一个Buffer包,而每个Buffer包用户设置的为1MB,这样算下来,30K用户,确实会积压30GB的发送缓存:
+后来通过计算,发现确实由于网络带宽瓶颈每个用户积压一个 Buffer 包,而每个 Buffer 包用户设置的为 1MB,这样算下来,30K 用户,确实会积压 30GB 的发送缓存:
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-10264ff3561e6ddc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
@@ -228,11 +233,10 @@ static std::shared_ptr getSharedMmap(const string &file_path, int64_t &fil
![图片.png](https://upload-images.jianshu.io/upload_images/8409177-d305041f6b99e04a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/600)
-
## 结论
-通过上面的经历,我们发现zlmediakit已经足以支撑30K/50Gb级别的https-hls并发能力, 理论上,http-hls相比https-hls要少1次内存拷贝,和1次加密,性能应该要好很多;那么zlmediakit的性能上限在哪里?天知道!毕竟,我已经没有这么豪华的配置供我压测了;在此,我们先立一个保守的flag吧:
-**单机 100K/100Gb级别 hls并发能力。**
+通过上面的经历,我们发现 zlmediakit 已经足以支撑 30K/50Gb 级别的 https-hls 并发能力, 理论上,http-hls 相比 https-hls 要少 1 次内存拷贝,和 1 次加密,性能应该要好很多;那么 zlmediakit 的性能上限在哪里?天知道!毕竟,我已经没有这么豪华的配置供我压测了;在此,我们先立一个保守的 flag 吧:
-那其他协议呢? 我觉得应该不输hls。
+**单机 100K/100Gb 级别 hls 并发能力。**
+那其他协议呢? 我觉得应该不输 hls。
diff --git a/src/zh/reference/development_log/rtsp_performance_optimization.md b/src/zh/reference/development_log/rtsp_performance_optimization.md
index dd89350..4f50d32 100644
--- a/src/zh/reference/development_log/rtsp_performance_optimization.md
+++ b/src/zh/reference/development_log/rtsp_performance_optimization.md
@@ -2,68 +2,76 @@
title: RTSP性能优化
order: 1
---
+
## 概述
-在最近ZLMediaKit的一次提交中,我对rtsp服务器的性能做了一次[改进](https://github.com/xiongziliang/ZLMediaKit/commit/b169f94cce1ecbab50248f25ee3b33dd40602fe1),本次改进中,核心的思想是:
-- **缓存时间戳相同的RTP包(意味着是同一帧数据),作为一个数据包进行分发**。
-理论上,这样做可以大大**减少多线程分发时线程切换次数、多余发送逻辑代码的执行以及系统调用次数**,预期在不增加播放延时的情况下能大幅提高rtsp服务器的性能.
+在最近 ZLMediaKit 的一次提交中,我对 rtsp 服务器的性能做了一次[改进](https://github.com/xiongziliang/ZLMediaKit/commit/b169f94cce1ecbab50248f25ee3b33dd40602fe1),本次改进中,核心的思想是:
+
+- **缓存时间戳相同的 RTP 包(意味着是同一帧数据),作为一个数据包进行分发**。
+
+理论上,这样做可以大大**减少多线程分发时线程切换次数、多余发送逻辑代码的执行以及系统调用次数**,预期在不增加播放延时的情况下能大幅提高 rtsp 服务器的性能.
## 测试
-为了验证本次优化的预期目标,我在linux服务器上做了一系列的测试对比,以下是测试环境:
+
+为了验证本次优化的预期目标,我在 linux 服务器上做了一系列的测试对比,以下是测试环境:
- 操作系统:ubuntu16 desktop 64bit
-- cpu: 4核心的Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
-- 编译器:gcc 5.4.0,开启Release编译(cmake -DCMAKE_BUILD_TYPE=Release)
-- malloc库:连接jemalloc
-- 网络: 127.0.0.1本地循环网络
+- cpu: 4 核心的 Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
+- 编译器:gcc 5.4.0,开启 Release 编译(cmake -DCMAKE_BUILD_TYPE=Release)
+- malloc 库:连接 jemalloc
+- 网络: 127.0.0.1 本地循环网络
- 测试客户端:[test_benchmark](https://github.com/xiongziliang/ZLMediaKit/blob/master/tests/test_benchmark.cpp)
- 测试服务器:[MediaServer](https://github.com/xiongziliang/ZLMediaKit/tree/master/server)
-- 测试码流:4K H264的RTSP流,通过MP4 Rtsp点播实现,文件200秒,190MB,码流大概8Mb/s
-- 测试方法:通过test_benchmark播放500路RTSP 4K点播,总码流大概4Gb/s,分别测试新老版本的MediaServer的进程。
-
+- 测试码流:4K H264 的 RTSP 流,通过 MP4 Rtsp 点播实现,文件 200 秒,190MB,码流大概 8Mb/s
+- 测试方法:通过 test_benchmark 播放 500 路 RTSP 4K 点播,总码流大概 4Gb/s,分别测试新老版本的 MediaServer 的进程。
## 测试数据
+
- 启动的播放器个数:
-![image](https://user-images.githubusercontent.com/11495632/78686734-f6d31180-7925-11ea-9ba3-864865a910b9.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78686734-f6d31180-7925-11ea-9ba3-864865a910b9.png)
- 实时码流:
-![image](https://user-images.githubusercontent.com/11495632/78686849-1b2eee00-7926-11ea-9434-a4f943021be5.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78686849-1b2eee00-7926-11ea-9434-a4f943021be5.png)
## 性能对比
+
### 老版本数据
-- cpu使用率(浮动比较大,最高200%+):
-![image](https://user-images.githubusercontent.com/11495632/78687097-621ce380-7926-11ea-9adb-80ccbbfca1f3.png)
-![image](https://user-images.githubusercontent.com/11495632/78687391-b031e700-7926-11ea-9b81-0339d8d9dafd.png)
+
+- cpu 使用率(浮动比较大,最高 200%+):
+
+ ![image](https://user-images.githubusercontent.com/11495632/78687097-621ce380-7926-11ea-9adb-80ccbbfca1f3.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78687391-b031e700-7926-11ea-9b81-0339d8d9dafd.png)
- 性能分析(perf top):
-![image](https://user-images.githubusercontent.com/11495632/78687480-c8096b00-7926-11ea-9d72-f21fffa8fd7d.png)
-- 总结 : cpu占用主要发生在内核态的系统调用(syscall)、tcp_sendmsg、内存拷贝。
+ ![image](https://user-images.githubusercontent.com/11495632/78687480-c8096b00-7926-11ea-9d72-f21fffa8fd7d.png)
-### 新版本数据:
-- cpu使用率(浮动比较小,50%以下):
-![image](https://user-images.githubusercontent.com/11495632/78688226-9e9d0f00-7927-11ea-8d31-49d487f339b4.png)
-![image](https://user-images.githubusercontent.com/11495632/78687893-3b12e180-7927-11ea-9e41-653b771405de.png)
+- 总结: cpu 占用主要发生在内核态的系统调用(syscall)、tcp_sendmsg、内存拷贝。
-- 后面我又测试了2000个播放器,掉了一批,最后稳定在1800个左右,实时流量17.5Gb/s(单向)左右,cpu占用300%左右:
-![image](https://user-images.githubusercontent.com/11495632/78741558-39c7d000-798c-11ea-9860-6dc18db1ef0c.png)
-![image](https://user-images.githubusercontent.com/11495632/78741649-78f62100-798c-11ea-85a9-1810bf1deaf1.png)
-![image](https://user-images.githubusercontent.com/11495632/78741678-8d3a1e00-798c-11ea-9aec-dff834620781.png)
-![image](https://user-images.githubusercontent.com/11495632/78741720-ad69dd00-798c-11ea-83c6-1b0b57d79ba2.png)
+### 新版本数据
-- 性能分析(perf top):
-![image](https://user-images.githubusercontent.com/11495632/78688104-7a413280-7927-11ea-953b-d3b9a4c5ed0c.png)
+- cpu 使用率(浮动比较小,50%以下):
-- 总结 : cpu占用主要发生在内核态内存拷贝,系统调用(syscall)、tcp_sendmsg的开销很小。
+ ![image](https://user-images.githubusercontent.com/11495632/78688226-9e9d0f00-7927-11ea-8d31-49d487f339b4.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78687893-3b12e180-7927-11ea-9e41-653b771405de.png)
+- 后面我又测试了 2000 个播放器,掉了一批,最后稳定在 1800 个左右,实时流量 17.5Gb/s(单向)左右,cpu 占用 300%左右:
+ ![image](https://user-images.githubusercontent.com/11495632/78741558-39c7d000-798c-11ea-9860-6dc18db1ef0c.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741649-78f62100-798c-11ea-85a9-1810bf1deaf1.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741678-8d3a1e00-798c-11ea-9aec-dff834620781.png)
+ ![image](https://user-images.githubusercontent.com/11495632/78741720-ad69dd00-798c-11ea-83c6-1b0b57d79ba2.png)
-## 总结
-本次性能测试基本证明了预想,性能提升大概有4倍以上。
-本机器为i7-4790 4核心8线程的,所以cpu占用率最高为800%,现在ZLMediaKit在上面支撑500个4K RTSP播放器,实时流量大概4Gb/s时cpu使用率50%不到,通过简单换算,该cpu可以支撑大概8000个4K RTSP播放器,实时流量最高能达到64Gb/s,考虑到性能折损,我们保守估计可以支持6000个4K RTSP播放器,50Gb/s的流量。
+- 性能分析(perf top):
-## 最后
-在ZLMediaKit流媒体服务器中,通过智能指针引用计数的方式实现了多线程的数据分发,不管分发多少次,数据拷贝次数都是固定的,所以ZLMediaKit可以达到如此夸张的性能参数,但是在测试中,我们也能发现,性能占用已经大部分发生在内核态了,应用层的cpu占用反而不是瓶颈了。这是因为在内核态,写socket缓存需要做内存拷贝,随着播放器个数的增加,内存拷贝会越来越多,此时性能瓶颈不再是应用层,而是由于内存带宽瓶颈导致的内核性能瓶颈。
+ ![image](https://user-images.githubusercontent.com/11495632/78688104-7a413280-7927-11ea-953b-d3b9a4c5ed0c.png)
+
+- 总结:cpu 占用主要发生在内核态内存拷贝,系统调用(syscall)、tcp_sendmsg 的开销很小。
+## 总结
+本次性能测试基本证明了预想,性能提升大概有 4 倍以上。
+本机器为 i7-4790 4 核心 8 线程的,所以 cpu 占用率最高为 800%,现在 ZLMediaKit 在上面支撑 500 个 4K RTSP 播放器,实时流量大概 4Gb/s 时 cpu 使用率 50%不到,通过简单换算,该 cpu 可以支撑大概 8000 个 4K RTSP 播放器,实时流量最高能达到 64Gb/s,考虑到性能折损,我们保守估计可以支持 6000 个 4K RTSP 播放器,50Gb/s 的流量。
+## 最后
+在 ZLMediaKit 流媒体服务器中,通过智能指针引用计数的方式实现了多线程的数据分发,不管分发多少次,数据拷贝次数都是固定的,所以 ZLMediaKit 可以达到如此夸张的性能参数,但是在测试中,我们也能发现,性能占用已经大部分发生在内核态了,应用层的 cpu 占用反而不是瓶颈了。这是因为在内核态,写 socket 缓存需要做内存拷贝,随着播放器个数的增加,内存拷贝会越来越多,此时性能瓶颈不再是应用层,而是由于内存带宽瓶颈导致的内核性能瓶颈。
diff --git a/src/zh/reference/documents/exclusive_features.md b/src/zh/reference/documents/exclusive_features.md
index 363a2b7..2b0dfc2 100644
--- a/src/zh/reference/documents/exclusive_features.md
+++ b/src/zh/reference/documents/exclusive_features.md
@@ -1,13 +1,14 @@
---
title: ZLMediakit独家特性介绍
---
+
## 1、先播放后推流
- 痛点:推流成功前不能提前播放
-- 场景介绍:
+- 场景介绍:
- 有些及时推流的场景,存在推流和播放同时发生的场景,这种场景一般是一对一的,譬如说基于rtmp推流的行车记录仪,用户在调阅车载摄像头视频的,下发推流命令给设备时,同时开始播放视频,如果播放请求先于推流到达流媒体服务器,那么流媒体服务器通常会立即返回流未找到的错误,为了解决这个问题,一般的解决方案是,通过设备确认推流成功再开启播放,但是这样往往会增加视频打开延时,拉低用户体验。zlmediakit针对此场景作出特别优化,可以在流不存在时,先不回复播放器,等推流成功后再返回播放成功,如果超时时间内,推流还不上线,那么再返回播放流不存在错误,通过配置文件可以修改此延时:
+ 有些及时推流的场景,存在推流和播放同时发生的场景,这种场景一般是一对一的,譬如说基于 rtmp 推流的行车记录仪,用户在调阅车载摄像头视频的,下发推流命令给设备时,同时开始播放视频,如果播放请求先于推流到达流媒体服务器,那么流媒体服务器通常会立即返回流未找到的错误,为了解决这个问题,一般的解决方案是,通过设备确认推流成功再开启播放,但是这样往往会增加视频打开延时,拉低用户体验。zlmediakit 针对此场景作出特别优化,可以在流不存在时,先不回复播放器,等推流成功后再返回播放成功,如果超时时间内,推流还不上线,那么再返回播放流不存在错误,通过配置文件可以修改此延时:
```ini
[general]
@@ -21,14 +22,13 @@ title: ZLMediakit独家特性介绍
> 提示: 此功能同样适用于拉流,通过该功能可以实现按需推拉流。
-
## 2、无人观看事件
- 痛点: 推流无人观看时白白浪费流量
- 场景介绍:
- 在一些物联网应用场景,设备推流给服务端,用户通过app查看设备视频,当用户关闭app时,设备应该停止推流以节省流量。为了实现该功能,一般的解决方案是播放端通过发送心跳维持设备推流,但是这样往往存在状态的不确定性,以及增加系统复杂度(想想app、web、小程序端同时维持推流心跳的场景)。针对此种场景,zlmediakit提供播放用户统计功能,在观看数为0时会触发无人观看事件,用户通过接收zlmediakit的 hook(http请求),可以返回是否让zlmediakit关闭该推流(或拉流),hook地址配置文件为:
+ 在一些物联网应用场景,设备推流给服务端,用户通过 app 查看设备视频,当用户关闭 app 时,设备应该停止推流以节省流量。为了实现该功能,一般的解决方案是播放端通过发送心跳维持设备推流,但是这样往往存在状态的不确定性,以及增加系统复杂度(想想 app、web、小程序端同时维持推流心跳的场景)。针对此种场景,zlmediakit 提供播放用户统计功能,在观看数为 0 时会触发无人观看事件,用户通过接收 zlmediakit 的 hook(http 请求),可以返回是否让 zlmediakit 关闭该推流(或拉流),hook 地址配置文件为:
```ini
[hook]
@@ -38,15 +38,15 @@ title: ZLMediakit独家特性介绍
on_stream_none_reader=https://127.0.0.1/index/hook/on_stream_none_reader
```
- > 提示: hook介绍[地址](../../guide/media_server/web_hook_api.md#13onstreamnonereader)
+ > 提示: hook 介绍[地址](../../guide/media_server/web_hook_api.md#13onstreamnonereader)
## 3、流未找到事件
-- 痛点: 我们只需对外提供播放url,而不是其他!
+- 痛点: 我们只需对外提供播放 url,而不是其他!
-- 场景介绍:
+- 场景介绍:
- 通常而言,我们通过播放url来分发视频内容,但是这些视频内容是及时生成的,在无人播放时,它并不存在(不存在推流或拉流代理)。这种场景下,通常的做法是用户需要限制客户端,因为提供的不是播放url,而是获取url的api,用户先获取播放url用于触发设备推流,然后才能播放,这种方式通常而言比较繁琐,需要特定的播放前逻辑,限制了一些应用场景。zlmediakit提供流未找到事件,可以汇报给你的业务服务器,告知流不存在,这个时候,你可以再从容控制设备开始推流,或者让zlmediakit开始拉流代理,hook地址配置文件为:
+ 通常而言,我们通过播放 url 来分发视频内容,但是这些视频内容是及时生成的,在无人播放时,它并不存在(不存在推流或拉流代理)。这种场景下,通常的做法是用户需要限制客户端,因为提供的不是播放 url,而是获取 url 的 api,用户先获取播放 url 用于触发设备推流,然后才能播放,这种方式通常而言比较繁琐,需要特定的播放前逻辑,限制了一些应用场景。zlmediakit 提供流未找到事件,可以汇报给你的业务服务器,告知流不存在,这个时候,你可以再从容控制设备开始推流,或者让 zlmediakit 开始拉流代理,hook 地址配置文件为:
```ini
[hook]
@@ -56,8 +56,7 @@ title: ZLMediakit独家特性介绍
on_stream_not_found=https://127.0.0.1/index/hook/on_stream_not_found
```
- > 提示: hook介绍[地址](../../guide/media_server/web_hook_api.md#14on_stream_not_found)
-
+ > 提示: hook 介绍[地址](../../guide/media_server/web_hook_api.md#14on_stream_not_found)
## 4、断连续推
@@ -65,11 +64,11 @@ title: ZLMediakit独家特性介绍
- 场景介绍:
- 一般推流器断开,服务器处理播放器的逻辑有这几种,一种是立即断开所有播放这个流的播放器,同时销毁推流器、播放器对象以便节省资源,这也是zlmediakit的默认做法。另外一种是以srs为代表,推流器断开后,基本什么也不做,不回收推流器开辟的资源,也不断开播放器(而是让播放器主动超时断开)。
+ 一般推流器断开,服务器处理播放器的逻辑有这几种,一种是立即断开所有播放这个流的播放器,同时销毁推流器、播放器对象以便节省资源,这也是 zlmediakit 的默认做法。另外一种是以 srs 为代表,推流器断开后,基本什么也不做,不回收推流器开辟的资源,也不断开播放器(而是让播放器主动超时断开)。
- srs这种处理方式有个好处,就是推流器重新推流后,播放器可以接着播放,用户体验比较好。坏处就是资源不能及时回收,如果有恶意链接不主动及时超时断开,可能会消耗服务器大量的文件描述符资源,同时由于推流器创建的媒体源资源无法主动释放,当创建很多个推流时,内存占用不能及时降低。
+ srs 这种处理方式有个好处,就是推流器重新推流后,播放器可以接着播放,用户体验比较好。坏处就是资源不能及时回收,如果有恶意链接不主动及时超时断开,可能会消耗服务器大量的文件描述符资源,同时由于推流器创建的媒体源资源无法主动释放,当创建很多个推流时,内存占用不能及时降低。
- zlmediakit现在针对这种场景,新增支持断连续推功能,解决了推流重连导致播放器断开的问题,也解决了资源无法及时回收的弊端,做法是,在推流器断开时,延时销毁媒体源资源对象(同时延时断开播放器),当推流器再次推流时,复用该资源对象,播放器可以接着观看视频;如果超时后,推流器未上线,那么再断开播放器并回收所有资源。超时延时配置文件为:
+ zlmediakit 现在针对这种场景,新增支持断连续推功能,解决了推流重连导致播放器断开的问题,也解决了资源无法及时回收的弊端,做法是,在推流器断开时,延时销毁媒体源资源对象(同时延时断开播放器),当推流器再次推流时,复用该资源对象,播放器可以接着观看视频;如果超时后,推流器未上线,那么再断开播放器并回收所有资源。超时延时配置文件为:
```ini
[general]
@@ -79,13 +78,12 @@ title: ZLMediakit独家特性介绍
continue_push_ms=15000
```
-
- 实现代码片段:
- ```c++
+ ```cpp
void RtmpSession::onError(const SockException& err) {
//省略无关代码
-
+
GET_CONFIG(uint32_t, continue_push_ms, General::kContinuePushMS);
if (_push_src && continue_push_ms) {
//取消推流对象所有权
@@ -95,11 +93,11 @@ title: ZLMediakit独家特性介绍
getPoller()->doDelayTask(continue_push_ms, [push_src]() { return 0; });
}
}
-
+
void RtmpSession::onCmd_publish(AMFDecoder &dec) {
//省略大量无关代码
auto src = MediaSource::find(RTMP_SCHEMA, _media_info._vhost, _media_info._app, _media_info._streamid);
-
+
while (src) {
//尝试断连后继续推流
auto rtmp_src = dynamic_pointer_cast(src);
@@ -122,16 +120,15 @@ title: ZLMediakit独家特性介绍
}
```
- > 提示:断连续推功能支持rtsp/rtmp/webrtc推流。
-
+ > 提示:断连续推功能支持 rtsp/rtmp/webrtc 推流。
## 5、集群部署
-- 痛点: 溯源方式单一,边沿服务器不能使用HLS。
+- 痛点: 溯源方式单一,边沿服务器不能使用 HLS。
- 场景介绍:
- 一般流媒体集群实现方式采用溯源方式实现,服务器分为源站和边沿站。源站一般用于接收推流,它一般不直接承载用户的播放请求,而是通过边沿服务器向其拉流同时分发给播放器,通过该模式可以支持海量的用户播放请求。srs很早之前已经通过配置文件的方式支持该功能,由于zlmediakit比较早也提供按需拉流的功能,本质上也支持溯源模式的集群,不过用户需要对接hook和api,开发门槛比较高,所以最近zlmediakit也支持了通过配置文件的方式来实现集群模式,配置文件如下:
+ 一般流媒体集群实现方式采用溯源方式实现,服务器分为源站和边沿站。源站一般用于接收推流,它一般不直接承载用户的播放请求,而是通过边沿服务器向其拉流同时分发给播放器,通过该模式可以支持海量的用户播放请求。srs 很早之前已经通过配置文件的方式支持该功能,由于 zlmediakit 比较早也提供按需拉流的功能,本质上也支持溯源模式的集群,不过用户需要对接 hook 和 api,开发门槛比较高,所以最近 zlmediakit 也支持了通过配置文件的方式来实现集群模式,配置文件如下:
```ini
[cluster]
@@ -149,39 +146,37 @@ title: ZLMediakit独家特性介绍
timeout_sec=15
```
- zlmediakit的溯源方式支持rtsp/rtmp/hls/http-ts/http-flv, 方式多样丰富,同时源站不分主备,采用round robin方式来实现源站的负载均衡。需要指出的是,由于zlmediakit很早就支持hls的按需拉流功能,所以zlmediakit的边沿站也支持hls协议(其实支持zlmediakit任意支持的协议),这点是srs不具备的。
-
- 另外需要指出的是,由于zlmediakit同时支持rtsp和webrtc,而它们两者都是基于rtp的,在zlmediakit内部,无须转协议简单处理后就可互联互通,所以使用zlmediakit来做大规模的webrtc低延时直播已经成为可能;相较于传统的基于rtmp的cdn,rtsp更适合作为webrtc的cdn基础传输协议,开发者不需要处理繁琐的解复用复用逻辑,即可平滑的实现rtsp与webrtc的互转。
+ zlmediakit 的溯源方式支持 rtsp/rtmp/hls/http-ts/http-flv, 方式多样丰富,同时源站不分主备,采用 round robin 方式来实现源站的负载均衡。需要指出的是,由于 zlmediakit 很早就支持 hls 的按需拉流功能,所以 zlmediakit 的边沿站也支持 hls 协议(其实支持 zlmediakit 任意支持的协议),这点是 srs 不具备的。
+ 另外需要指出的是,由于 zlmediakit 同时支持 rtsp 和 webrtc,而它们两者都是基于 rtp 的,在 zlmediakit 内部,无须转协议简单处理后就可互联互通,所以使用 zlmediakit 来做大规模的 webrtc 低延时直播已经成为可能;相较于传统的基于 rtmp 的 cdn,rtsp 更适合作为 webrtc 的 cdn 基础传输协议,开发者不需要处理繁琐的解复用复用逻辑,即可平滑的实现 rtsp 与 webrtc 的互转。
-## 6、WebRTC单端口、多线程、支持连接迁移
+## 6、WebRTC 单端口、多线程、支持连接迁移
-- 痛点:支持多线程的webrtc服务器不支持单端口,支持单端口的不支持多线程(同时可能不支持链接迁移)
+- 痛点:支持多线程的 webrtc 服务器不支持单端口,支持单端口的不支持多线程(同时可能不支持链接迁移)
- 场景介绍:
- 由于webrtc传输是基于udp协议的,传统的webrtc服务器都是多端口模式,譬如janus/mediasoup。这给部署和管理带来极大痛苦,而且由于端口个数有限(理论上限6万多),每个webrtc客户端要占用1至4个端口,受限于端口数量,一台webrtc服务器最多可以承载1~6万左右的客户端数。
-
- 而支持单端口的webrtc服务器(譬如srs),又不支持多线程;由于webrtc计算复杂度(加解密)远大于直播,其性能跟直播比有数量级的差距,所以往往单线程在webrtc的应用场景已经力不从心。
+ 由于 webrtc 传输是基于 udp 协议的,传统的 webrtc 服务器都是多端口模式,譬如 janus/mediasoup。这给部署和管理带来极大痛苦,而且由于端口个数有限(理论上限 6 万多),每个 webrtc 客户端要占用 1 至 4 个端口,受限于端口数量,一台 webrtc 服务器最多可以承载 1~6 万左右的客户端数。
- zlmediakit针对这些痛点,提出了最佳解决方案:
+ 而支持单端口的 webrtc 服务器(譬如 srs),又不支持多线程;由于 webrtc 计算复杂度(加解密)远大于直播,其性能跟直播比有数量级的差距,所以往往单线程在 webrtc 的应用场景已经力不从心。
- - 支持单udp端口部署,一个udp端口承载所有客户端。
- - 单udp端口支持多线程,单端口多次bind/connect方式实现一个客户端对应一个fd,fd均匀分配到不同线程。
- - 用户网络迁移时(譬如wifi切换为4G),通过stun包锁定用户,实现无感知的连接迁移,用户体验不中断。
+ zlmediakit 针对这些痛点,提出了最佳解决方案:
- 以上3个特性都同时具备的,目前在开源界唯zlmediakit一家。
+ - 支持单 udp 端口部署,一个 udp 端口承载所有客户端。
+ - 单 udp 端口支持多线程,单端口多次 bind/connect 方式实现一个客户端对应一个 fd,fd 均匀分配到不同线程。
+ - 用户网络迁移时(譬如 wifi 切换为 4G),通过 stun 包锁定用户,实现无感知的连接迁移,用户体验不中断。
- > 提示: 关于怎么解决webrtc单端口连接迁移和多线程连接迁移时线程安全问题的请观看该[视频](https://mp.weixin.qq.com/s?t=pages/video_detail_new&scene=23&vid=wxv_2170272938552328197&__biz=MzkzNjI5ODIyMg==&mid=2247483673&idx=1&sn=14bc138d91292a1c256c138c822d9c40&vidsn=#wechat_redirect)
+ 以上 3 个特性都同时具备的,目前在开源界唯 zlmediakit 一家。
+ > 提示: 关于怎么解决 webrtc 单端口连接迁移和多线程连接迁移时线程安全问题的请观看该[视频](https://mp.weixin.qq.com/s?t=pages/video_detail_new&scene=23&vid=wxv_2170272938552328197&__biz=MzkzNjI5ODIyMg==&mid=2247483673&idx=1&sn=14bc138d91292a1c256c138c822d9c40&vidsn=#wechat_redirect)
-## 7、HLS播放的长链接化
- zlmediakit通过cookie追踪技术实现hls短连接的长链接化,依赖该特性,zlm的hls服务器具备了以下独家特性:
-- HLS播放鉴权,并且播放途中无须再鉴权。
-- HLS播放流量统计,可以统计播放器播放途中所有短连接消耗流量总数。
-- HLS按需拉流,可以先播放zlmediakit的HLS链接,zlmediakit再去溯源拉流代理。
-- HLS无人观看时自动停止溯源拉流代理或掐断上游推流。
+## 7、HLS 播放的长链接化
-另外,zlmediakit的hls服务器性能已优化至极致(通过共享ts mmap和内存m3u8实现),单进程可以承载10W级别hls播放器,100Gb/s级别带宽。
+zlmediakit 通过 cookie 追踪技术实现 hls 短连接的长链接化,依赖该特性,zlm 的 hls 服务器具备了以下独家特性:
+- HLS 播放鉴权,并且播放途中无须再鉴权。
+- HLS 播放流量统计,可以统计播放器播放途中所有短连接消耗流量总数。
+- HLS 按需拉流,可以先播放 zlmediakit 的 HLS 链接,zlmediakit 再去溯源拉流代理。
+- HLS 无人观看时自动停止溯源拉流代理或掐断上游推流。
+另外,zlmediakit 的 hls 服务器性能已优化至极致(通过共享 ts mmap 和内存 m3u8 实现),单进程可以承载 10W 级别 hls 播放器,100Gb/s 级别带宽。
diff --git a/src/zh/reference/documents/high_concurrency_implementation_principle.md b/src/zh/reference/documents/high_concurrency_implementation_principle.md
index 5489b5b..ab7f0ec 100644
--- a/src/zh/reference/documents/high_concurrency_implementation_principle.md
+++ b/src/zh/reference/documents/high_concurrency_implementation_principle.md
@@ -1,47 +1,48 @@
---
title: ZLMediaKit高并发实现原理
---
-# 项目介绍
-[ZLMediaKit](https://github.com/xiongziliang/ZLMediaKit)是一套高性能的流媒体服务框架,目前支持rtmp/rtsp/hls/http-flv流媒体协议。该项目已支持linux、macos、windows、ios、android平台,支持的编码格式包括H264、AAC、H265(仅rtsp支持H265);采用的模型是多线程IO多路复用非阻塞式编程(linux下采用epoll、其他平台采用select)。
-
-该框架基于C++11开发,避免使用裸指针,减少内存拷贝,代码精简可靠,并发性能优异,在linux平台下,单一进程即可充分利用多核CPU的优势;最大限度的榨干CPU、网卡性能;轻松达到万兆网卡性能极限。同时也能在高性能的同时,做到极低延时,画面秒开。
-
-目前ZLMediaKit经过多次版本迭代,编程模型多次升级优化;已经趋于成熟稳定,也在各种生产环境得到了验证,本文主要讨论ZLMediaKit高性能实现原理以及项目特点。
+## 项目介绍
-# 网络模型对比
+[ZLMediaKit](https://github.com/xiongziliang/ZLMediaKit)是一套高性能的流媒体服务框架,目前支持 rtmp/rtsp/hls/http-flv 流媒体协议。该项目已支持 linux、macos、windows、ios、android 平台,支持的编码格式包括 H264、AAC、H265(仅 rtsp 支持 H265);采用的模型是多线程 IO 多路复用非阻塞式编程(linux 下采用 epoll、其他平台采用 select)。
-不同于SRS的单线程多协程、node.js/redis的单线程、NGINX的多进程模型;ZLMediaKit采用的是单进程多线程模型。那么为什么ZLMediaKit要采用这样的编程模型呢?
+该框架基于 C++11 开发,避免使用裸指针,减少内存拷贝,代码精简可靠,并发性能优异,在 linux 平台下,单一进程即可充分利用多核 CPU 的优势;最大限度的榨干 CPU、网卡性能;轻松达到万兆网卡性能极限。同时也能在高性能的同时,做到极低延时,画面秒开。
-作为一个多年的C++服务器后台开发工程师,多年的工作经验告诉我,作为一个服务器程序,对于稳定性要求极高;一个服务器可以性能差点,但是绝不能轻易core dump;服务中断、重启、异常,对于一个线上已运营项目来说结果是灾难性的。那么我们该怎么确保服务器的稳定?目前有以下手段:
+目前 ZLMediaKit 经过多次版本迭代,编程模型多次升级优化;已经趋于成熟稳定,也在各种生产环境得到了验证,本文主要讨论 ZLMediaKit 高性能实现原理以及项目特点。
+
+## 网络模型对比
+
+不同于 SRS 的单线程多协程、node.js/redis 的单线程、NGINX 的多进程模型;ZLMediaKit 采用的是单进程多线程模型。那么为什么 ZLMediaKit 要采用这样的编程模型呢?
+
+作为一个多年的 C++服务器后台开发工程师,多年的工作经验告诉我,作为一个服务器程序,对于稳定性要求极高;一个服务器可以性能差点,但是绝不能轻易 core dump;服务中断、重启、异常,对于一个线上已运营项目来说结果是灾难性的。那么我们该怎么确保服务器的稳定?目前有以下手段:
- 单线程模型
- 单线程+协程
- 单线程+多进程
- 多线程+锁
-- 弃用C/C++
+- 弃用 C/C++
-采用单线程模型的优点是,服务器简单可靠,不用考虑资源竞争互斥的问题,这样可以比较容易做到高稳定性;采用此模型的典型代表项目有 redis、node.js。但是由于是单线程模型,所以弊端也比较明显;那就是在多核cpu上不能充分利用多核CPU的算力,性能瓶颈主要在于CPU(大家应该有过在redis中执行keys *慢慢等待的经历)。
+采用单线程模型的优点是,服务器简单可靠,不用考虑资源竞争互斥的问题,这样可以比较容易做到高稳定性;采用此模型的典型代表项目有 redis、node.js。但是由于是单线程模型,所以弊端也比较明显;那就是在多核 cpu 上不能充分利用多核 CPU 的算力,性能瓶颈主要在于 CPU(大家应该有过在 redis 中执行 keys \*慢慢等待的经历)。
![img](https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3069000473,466332746&fm=26&gp=0.jpg)
-单线程+协程的方案本质上与纯单线程模型无区别,它们的区别主要编程风格上。纯单线程模型使用的是非阻塞式处处回调方式实现高并发,这种模型会有所谓的回调地狱的问题,编程起来会比较麻烦。而单线程+协程的方案是简化编程方式,采用自然的阻塞式编程风格,在协程库内部管理任务调度,本质也是非阻塞的。但是协程库涉及的比较底层,跟系统息息相关,所以跨平台不是很好做,而且设计实现一个协程库门槛较高。SRS采用就是这编程模型,由于协程库的限制,SRS不能在windows上运行。
+单线程+协程的方案本质上与纯单线程模型无区别,它们的区别主要编程风格上。纯单线程模型使用的是非阻塞式处处回调方式实现高并发,这种模型会有所谓的回调地狱的问题,编程起来会比较麻烦。而单线程+协程的方案是简化编程方式,采用自然的阻塞式编程风格,在协程库内部管理任务调度,本质也是非阻塞的。但是协程库涉及的比较底层,跟系统息息相关,所以跨平台不是很好做,而且设计实现一个协程库门槛较高。SRS 采用就是这编程模型,由于协程库的限制,SRS 不能在 windows 上运行。
-为了解决上述单线程模型的问题,很多服务器采用单线程多进程的编程模型;在这种模型下,既有单线程模型的简单可靠的特性,又能充分发挥多核CPU的性能,而且某个进程挂了也不会影响其他进程,像NGINX就是这种编程模型;但是这种模型也有其局限性。在这种模型下,会话间是相互隔离的,两个会话可能运行在不同的进程上;这样就导致了会话间通信的困难。比如说A用户连接在服务器A进程上,B用户连接在服务器B进程上;如果两者之间要完成某种数据交互,那么会异常困难,这样必须通过进程间通信来完成。而进程间通信代价和开销比较大,编程起来也比较困难。但是如果会话间无需数据交互(例如http服务器),那么这种模型是特别适合的,所以NGINX作为http服务器也是非常成功的,但是如果是譬如即时聊天的那种需要会话间通信的服务,那么这种开发模型不是很适合。不过现在越来越多的服务都需要支持分布式集群部署,所以单线程多进程方案的缺陷越来越不明显。
+为了解决上述单线程模型的问题,很多服务器采用单线程多进程的编程模型;在这种模型下,既有单线程模型的简单可靠的特性,又能充分发挥多核 CPU 的性能,而且某个进程挂了也不会影响其他进程,像 NGINX 就是这种编程模型;但是这种模型也有其局限性。在这种模型下,会话间是相互隔离的,两个会话可能运行在不同的进程上;这样就导致了会话间通信的困难。比如说 A 用户连接在服务器 A 进程上,B 用户连接在服务器 B 进程上;如果两者之间要完成某种数据交互,那么会异常困难,这样必须通过进程间通信来完成。而进程间通信代价和开销比较大,编程起来也比较困难。但是如果会话间无需数据交互(例如 http 服务器),那么这种模型是特别适合的,所以 NGINX 作为 http 服务器也是非常成功的,但是如果是譬如即时聊天的那种需要会话间通信的服务,那么这种开发模型不是很适合。不过现在越来越多的服务都需要支持分布式集群部署,所以单线程多进程方案的缺陷越来越不明显。
-由于C/C++是种强类型静态语言,异常处理简单粗暴,动不动就core dump。C/C++的设计理念就是发现错误及早暴露,在某种意义上来说,崩溃也是种好事,因为这样会引起你的重视,让你能及早发现定位并解决问题,而不是把问题拖延到无法解决的时候再暴露给你。但是这么做对一般人来说,C/C++就不是很友好了,人类并不像机器那样严谨,有点疏忽在所难免,况且有些小问题也无伤大雅,并不需要毁灭式的core dump来应对。而且C/C++的学习曲线异常艰难困苦,很多人好几年也不得要领,所以很多人表示纷纷弃坑,转投 go / erlang / node.js之类。
+由于 C/C++是种强类型静态语言,异常处理简单粗暴,动不动就 core dump。C/C++的设计理念就是发现错误及早暴露,在某种意义上来说,崩溃也是种好事,因为这样会引起你的重视,让你能及早发现定位并解决问题,而不是把问题拖延到无法解决的时候再暴露给你。但是这么做对一般人来说,C/C++就不是很友好了,人类并不像机器那样严谨,有点疏忽在所难免,况且有些小问题也无伤大雅,并不需要毁灭式的 core dump 来应对。而且 C/C++的学习曲线异常艰难困苦,很多人好几年也不得要领,所以很多人表示纷纷弃坑,转投 go / erlang / node.js 之类。
-但是C/C++由于其性能优越性,以及历史原因,在某些场景下是不二选择,而且C/C++才是真正的跨平台语言;况且随着智能指针的推出,内存管理不再是难题;而lambda语法的支持,让程序上下文绑定不再困难。随着C++新特性的支持,编译器静态反射机制的完善,现代C++编程愈发简便快捷。ZLMediaKit采用的就是C++11新标准以及相关理念完成的高性能流媒体服务框架。
+但是 C/C++由于其性能优越性,以及历史原因,在某些场景下是不二选择,而且 C/C++才是真正的跨平台语言;况且随着智能指针的推出,内存管理不再是难题;而 lambda 语法的支持,让程序上下文绑定不再困难。随着 C++新特性的支持,编译器静态反射机制的完善,现代 C++编程愈发简便快捷。ZLMediaKit 采用的就是 C++11 新标准以及相关理念完成的高性能流媒体服务框架。
-与上面其它编程模型不同,ZLMediaKit采用的是多线程开发模型;与传统的多线程模型不同;ZLMediaKit采用了C++11的智能指针来做内存管理,在线程切换时可以完美的管理内存在多线程下共享以及其生命周期。同时互斥锁的粒度消减至极致,几乎可以忽略不计。所以采用多线程模型的ZLMediaKit性能损耗极低,每条线程的性能几乎可以媲美单线程模型,同时也可以充分榨干CPU的每一核心性能。
+与上面其它编程模型不同,ZLMediaKit 采用的是多线程开发模型;与传统的多线程模型不同;ZLMediaKit 采用了 C++11 的智能指针来做内存管理,在线程切换时可以完美的管理内存在多线程下共享以及其生命周期。同时互斥锁的粒度消减至极致,几乎可以忽略不计。所以采用多线程模型的 ZLMediaKit 性能损耗极低,每条线程的性能几乎可以媲美单线程模型,同时也可以充分榨干 CPU 的每一核心性能。
-# 网络模型详述
+## 网络模型详述
-ZLMediaKit在启动时会根据cpu核心数自动创建若干个epoll实例(非linux平台为select);这些epoll实例都会有一个线程来运行`epoll_wait`函数来等待事件的触发。
+ZLMediaKit 在启动时会根据 cpu 核心数自动创建若干个 epoll 实例(非 linux 平台为 select);这些 epoll 实例都会有一个线程来运行`epoll_wait`函数来等待事件的触发。
-以ZLMediaKit的RTMP服务为例,在创建一个`TcpServer`时,ZLMediaKit会把这个Tcp服务的监听套接字加入到每一个epoll实例,这样如果收到新的RTMP播放请求,那么多个epoll实例会在内核的调度下,自动选择负载较轻的线程触发accept事件,以下是代码片段:
+以 ZLMediaKit 的 RTMP 服务为例,在创建一个`TcpServer`时,ZLMediaKit 会把这个 Tcp 服务的监听套接字加入到每一个 epoll 实例,这样如果收到新的 RTMP 播放请求,那么多个 epoll 实例会在内核的调度下,自动选择负载较轻的线程触发 accept 事件,以下是代码片段:
-```c++
+```cpp
template
void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog = 1024) {
start_l(port,host,backlog);
@@ -53,7 +54,7 @@ void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog
}
auto &serverRef = _clonedServer[poller.get()];
if(!serverRef){
- //绑定epoll实例
+ //绑定epoll实例
serverRef = std::make_shared(poller);
}
serverRef->cloneFrom(*this);
@@ -62,32 +63,30 @@ void start(uint16_t port, const std::string& host = "0.0.0.0", uint32_t backlog
void cloneFrom(const TcpServer &that){
- if(!that._socket){
- throw std::invalid_argument("TcpServer::cloneFrom other with null socket!");
- }
- _sessionMaker = that._sessionMaker;
- //克隆一个相同fd的Socket对象
- _socket->cloneFromListenSocket(*(that._socket));
- _timer = std::make_shared(2, [this]()->bool {
- this->onManagerSession();
- return true;
- },_poller);
- this->mINI::operator=(that);
+ if(!that._socket){
+ throw std::invalid_argument("TcpServer::cloneFrom other with null socket!");
+ }
+ _sessionMaker = that._sessionMaker;
+ //克隆一个相同fd的Socket对象
+ _socket->cloneFromListenSocket(*(that._socket));
+ _timer = std::make_shared(2, [this]()->bool {
+ this->onManagerSession();
+ return true;
+ },_poller);
+ this->mINI::operator=(that);
_cloned = true;
- }
+ }
```
+服务器在收到 accept 事件后,会创建一个`TcpSession`对象并绑定到该 epoll 实例(同时把与之对应的`peer fd`加入到相关 epoll 监听)。每一个 Tcp 连接都会对应一个`TcpSession`对象,在之后客户端与服务器的数据交互中,该`TcpSession`对象处理一切与之相关的业务数据,并且该对象之后生命周期内的一切事件都会由该 epoll 线程触发,这样服务器的每个 epoll 线程都能均匀的分派到合理的客户端数量。以下是服务器 accept 事件处理逻辑代码片段:
-
-服务器在收到accept事件后,会创建一个`TcpSession`对象并绑定到该epoll实例(同时把与之对应的`peer fd`加入到相关epoll监听)。每一个Tcp连接都会对应一个`TcpSession`对象,在之后客户端与服务器的数据交互中,该`TcpSession`对象处理一切与之相关的业务数据,并且该对象之后生命周期内的一切事件都会由该epoll线程触发,这样服务器的每个epoll线程都能均匀的分派到合理的客户端数量。以下是服务器accept事件处理逻辑代码片段:
-
-```c++
+```cpp
// 接收到客户端连接请求
virtual void onAcceptConnection(const Socket::Ptr & sock) {
- weak_ptr weakSelf = shared_from_this();
+ weak_ptr weakSelf = shared_from_this();
//创建一个TcpSession;这里实现创建不同的服务会话实例
- auto sessionHelper = _sessionMaker(weakSelf,sock);
- auto &session = sessionHelper->session();
+ auto sessionHelper = _sessionMaker(weakSelf,sock);
+ auto &session = sessionHelper->session();
//把本服务器的配置传递给TcpSession
session->attachServer(*this);
@@ -105,25 +104,25 @@ void cloneFrom(const TcpServer &that){
assert(success == true);
weak_ptr weakSession(session);
- //会话接收数据事件
- sock->setOnRead([weakSession](const Buffer::Ptr &buf, struct sockaddr *addr){
- //获取会话强引用
- auto strongSession=weakSession.lock();
- if(!strongSession) {
- //会话对象已释放
- return;
- }
+ //会话接收数据事件
+ sock->setOnRead([weakSession](const Buffer::Ptr &buf, struct sockaddr *addr){
+ //获取会话强引用
+ auto strongSession=weakSession.lock();
+ if(!strongSession) {
+ //会话对象已释放
+ return;
+ }
//TcpSession处理业务数据
- strongSession->onRecv(buf);
- });
+ strongSession->onRecv(buf);
+ });
- //会话接收到错误事件
- sock->setOnErr([weakSelf,weakSession,sessionId](const SockException &err){
- //在本函数作用域结束时移除会话对象
+ //会话接收到错误事件
+ sock->setOnErr([weakSelf,weakSession,sessionId](const SockException &err){
+ //在本函数作用域结束时移除会话对象
//目的是确保移除会话前执行其onError函数
//同时避免其onError函数抛异常时没有移除会话对象
- onceToken token(nullptr,[&](){
+ onceToken token(nullptr,[&](){
//移除掉会话
SessionMap::Instance().remove(sessionId);
auto strongSelf = weakSelf.lock();
@@ -138,59 +137,57 @@ void cloneFrom(const TcpServer &that){
}
strongSelf->_sessionMap.erase(sessionId);
});
- });
- //获取会话强应用
- auto strongSession=weakSession.lock();
+ });
+ //获取会话强应用
+ auto strongSession=weakSession.lock();
if(strongSession) {
//触发onError事件回调
- strongSession->onError(err);
- }
- });
- }
+ strongSession->onError(err);
+ }
+ });
+ }
```
+通过上诉描述,我们应该大概了解了 ZLMediaKit 的网络模型,通过这样的模型基本上能榨干 CPU 的算力,不过 CPU 算力如果使用不当 ,也可能白白浪费,使之做一些无用的事务,那么在 ZLMediaKit 中还有那些技术手段来提高性能呢?我们在下节展开论述。
+## 关闭互斥锁
-通过上诉描述,我们应该大概了解了ZLMediaKit的网络模型,通过这样的模型基本上能榨干CPU的算力,不过CPU算力如果使用不当 ,也可能白白浪费,使之做一些无用的事务,那么在ZLMediaKit中还有那些技术手段来提高性能呢?我们在下节展开论述。
-
-# 关闭互斥锁
+上一节论述中,我们知道`TcpSession`是 ZLMediaKit 中的关键元素,服务器大部分计算都在 TcpSession 内完成。一个`TcpSession`由一个 epoll 实例掌管其生命周期,其他线程不得直接操作该`TcpSession`对象(必须通过线程切换到对应的 epoll 线程来完成操作);所以从某种意义上来说`TcpSeesion`是单线程模型的;所以 ZLMediaKit 对于`TcpSession`所对应的网络 io 操作是无互斥锁保护的,ZLMediaKit 作为服务器模式运行,基本上是无锁的;这种情况下,锁对性能的影响几乎可以忽略不计。以下是 ZLMediaKit 关闭互斥锁的代码片段:
-上一节论述中,我们知道`TcpSession`是ZLMediaKit中的关键元素,服务器大部分计算都在TcpSession内完成。一个`TcpSession`由一个epoll实例掌管其生命周期,其他线程不得直接操作该`TcpSession`对象(必须通过线程切换到对应的epoll线程来完成操作);所以从某种意义上来说`TcpSeesion`是单线程模型的;所以ZLMediaKit对于`TcpSession`所对应的网络io操作是无互斥锁保护的,ZLMediaKit作为服务器模式运行,基本上是无锁的;这种情况下,锁对性能的影响几乎可以忽略不计。以下是ZLMediaKit关闭互斥锁的代码片段:
-
-```c++
+```cpp
virtual Socket::Ptr onBeforeAcceptConnection(const EventPoller::Ptr &poller){
- /**
- * 服务器模型socket是线程安全的,所以为了提高性能,关闭互斥锁
- * Socket构造函数第二个参数即为是否关闭互斥锁
- */
- return std::make_shared(poller,false);
- }
+ /**
+ * 服务器模型socket是线程安全的,所以为了提高性能,关闭互斥锁
+ * Socket构造函数第二个参数即为是否关闭互斥锁
+ */
+ return std::make_shared(poller,false);
+ }
//Socket对象的构造函数,第二个参数即为是否关闭互斥锁
Socket::Socket(const EventPoller::Ptr &poller,bool enableMutex) :
- _mtx_sockFd(enableMutex),
- _mtx_bufferWaiting(enableMutex),
- _mtx_bufferSending(enableMutex) {
- _poller = poller;
- if(!_poller){
- _poller = EventPollerPool::Instance().getPoller();
- }
+ _mtx_sockFd(enableMutex),
+ _mtx_bufferWaiting(enableMutex),
+ _mtx_bufferSending(enableMutex) {
+ _poller = poller;
+ if(!_poller){
+ _poller = EventPollerPool::Instance().getPoller();
+ }
_canSendSock = true;
- _readCB = [](const Buffer::Ptr &buf,struct sockaddr *) {
- WarnL << "Socket not set readCB";
- };
- _errCB = [](const SockException &err) {
- WarnL << "Socket not set errCB:" << err.what();
- };
- _acceptCB = [](Socket::Ptr &sock) {
- WarnL << "Socket not set acceptCB";
- };
- _flushCB = []() {return true;};
-
- _beforeAcceptCB = [](const EventPoller::Ptr &poller){
- return nullptr;
- };
+ _readCB = [](const Buffer::Ptr &buf,struct sockaddr *) {
+ WarnL << "Socket not set readCB";
+ };
+ _errCB = [](const SockException &err) {
+ WarnL << "Socket not set errCB:" << err.what();
+ };
+ _acceptCB = [](Socket::Ptr &sock) {
+ WarnL << "Socket not set acceptCB";
+ };
+ _flushCB = []() {return true;};
+
+ _beforeAcceptCB = [](const EventPoller::Ptr &poller){
+ return nullptr;
+ };
}
//MutexWrapper对象定义,可以选择是否关闭互斥锁
@@ -219,30 +216,28 @@ private:
```
-
-
-# 规避内存拷贝
+## 规避内存拷贝
传统的多线程模型下,做数据转发会存在线程切换的问题,为了确保线程安全,一般使用内存拷贝来规避该问题;而且对数据进行分包处理也很难做到不使用内存拷贝。但是流媒体这种业务逻辑,可能观看同一个直播的用户是海量的,如果每分发一次就做内存拷贝,那么开销是十分可观的,这将严重拖累服务器性能。
-ZLMediaKit在做媒体数据转发时,是不会做内存拷贝的,常规的C++多线程编程很难做到这一点,但是我们在C++11的加持下,利用引用计数,巧妙的解决了多线程内存生命周期管理的问题,以下是RTMP服务器做媒体数据分发规避内存拷贝的代码片段:
+ZLMediaKit 在做媒体数据转发时,是不会做内存拷贝的,常规的 C++多线程编程很难做到这一点,但是我们在 C++11 的加持下,利用引用计数,巧妙的解决了多线程内存生命周期管理的问题,以下是 RTMP 服务器做媒体数据分发规避内存拷贝的代码片段:
-```c++
+```cpp
void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
const Buffer::Ptr &buf, uint32_t ui32TimeStamp, int iChunkId){
if (iChunkId < 2 || iChunkId > 63) {
auto strErr = StrPrinter << "不支持发送该类型的块流 ID:" << iChunkId << endl;
throw std::runtime_error(strErr);
}
- //是否有扩展时间戳
+ //是否有扩展时间戳
bool bExtStamp = ui32TimeStamp >= 0xFFFFFF;
//rtmp头
- BufferRaw::Ptr bufferHeader = obtainBuffer();
- bufferHeader->setCapacity(sizeof(RtmpHeader));
- bufferHeader->setSize(sizeof(RtmpHeader));
- //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
- RtmpHeader *header = (RtmpHeader*) bufferHeader->data();
+ BufferRaw::Ptr bufferHeader = obtainBuffer();
+ bufferHeader->setCapacity(sizeof(RtmpHeader));
+ bufferHeader->setSize(sizeof(RtmpHeader));
+ //对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
+ RtmpHeader *header = (RtmpHeader*) bufferHeader->data();
header->flags = (iChunkId & 0x3f) | (0 << 6);
header->typeId = ui8Type;
set_be24(header->timeStamp, bExtStamp ? 0xFFFFFF : ui32TimeStamp);
@@ -252,23 +247,23 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
onSendRawData(bufferHeader);
//扩展时间戳字段
- BufferRaw::Ptr bufferExtStamp;
+ BufferRaw::Ptr bufferExtStamp;
if (bExtStamp) {
//生成扩展时间戳
- bufferExtStamp = obtainBuffer();
- bufferExtStamp->setCapacity(4);
- bufferExtStamp->setSize(4);
- set_be32(bufferExtStamp->data(), ui32TimeStamp);
- }
-
- //生成一个字节的flag,标明是什么chunkId
- BufferRaw::Ptr bufferFlags = obtainBuffer();
- bufferFlags->setCapacity(1);
- bufferFlags->setSize(1);
- bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6);
-
+ bufferExtStamp = obtainBuffer();
+ bufferExtStamp->setCapacity(4);
+ bufferExtStamp->setSize(4);
+ set_be32(bufferExtStamp->data(), ui32TimeStamp);
+ }
+
+ //生成一个字节的flag,标明是什么chunkId
+ BufferRaw::Ptr bufferFlags = obtainBuffer();
+ bufferFlags->setCapacity(1);
+ bufferFlags->setSize(1);
+ bufferFlags->data()[0] = (iChunkId & 0x3f) | (3 << 6);
+
size_t offset = 0;
- uint32_t totalSize = sizeof(RtmpHeader);
+ uint32_t totalSize = sizeof(RtmpHeader);
while (offset < buf->size()) {
if (offset) {
//发送trunkId
@@ -318,20 +313,20 @@ private:
```
-我们在发送RTP包时也是采用同样的原理来避免内存拷贝。
+我们在发送 RTP 包时也是采用同样的原理来避免内存拷贝。
-# 使用对象循环池
+## 使用对象循环池
-内存开辟销毁是全局互斥的,过多的new/delete 不仅降低程序性能,还会导致内存碎片。ZLMediaKit尽量使用循环池来避免这些问题,以下代码时RTP包循环池使用代码片段:
+内存开辟销毁是全局互斥的,过多的 new/delete 不仅降低程序性能,还会导致内存碎片。ZLMediaKit 尽量使用循环池来避免这些问题,以下代码时 RTP 包循环池使用代码片段:
-```c++
+```cpp
RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, unsigned int len, bool mark, uint32_t uiStamp) {
uint16_t ui16RtpLen = len + 12;
uint32_t ts = htonl((_ui32SampleRate / 1000) * uiStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
- //采用循环池来获取rtp对象
+ //采用循环池来获取rtp对象
auto rtppkt = ResourcePoolHelper::obtainObj();
unsigned char *pucRtp = rtppkt->payload;
pucRtp[0] = '$';
@@ -362,21 +357,19 @@ RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, unsigned int l
}
```
+## 设置 Socket 相关标志
+开启 TCP_NODELAY 后可以提高服务器响应速度,对于一些对延时要求比较敏感的服务(比如 ssh 服务),开启 TCP_NODELAY 标记比较重要。但是对于流媒体服务,由于数据是源源不断并且量也比较大,所以关闭 TCP_NODELAY 可以减少 ACK 包数量,充分利用带宽资源。
-# 设置Socket相关标志
+MSG_MORE 是另外一个提高网络吞吐量的标记;这个标记的作用是在发送数据时,服务器会缓存一定的数据然后再打包一次性发送出去;而像 RTSP 这种业务场景,MSG_MORE 标记就显得格外合适;因为 RTP 包一般都很小(小于 MTU),通过 MSG_MORE 标记可以极大减少数据包个数。
-开启TCP_NODELAY后可以提高服务器响应速度,对于一些对延时要求比较敏感的服务(比如ssh服务),开启TCP_NODELAY标记比较重要。但是对于流媒体服务,由于数据是源源不断并且量也比较大,所以关闭TCP_NODELAY可以减少ACK包数量,充分利用带宽资源。
+ZLMediaKit 在处理播放器时,握手期间是开启 TCP_NODELAY 并且关闭 MSG_MORE 的,这样做的目的是提高握手期间数据交互的延时,减少链接建立耗时,提高视频打开速度。在握手成功后,ZLMediaKit 会关闭 TCP_NODELAY 并打开 MSG_MORE;这样又能减少数据报文个数,提高网络利用率。
-MSG_MORE是另外一个提高网络吞吐量的标记;这个标记的作用是在发送数据时,服务器会缓存一定的数据然后再打包一次性发送出去;而像RTSP这种业务场景,MSG_MORE标记就显得格外合适;因为RTP包一般都很小(小于MTU),通过MSG_MORE标记可以极大减少数据包个数。
+## 批量数据发送
-ZLMediaKit在处理播放器时,握手期间是开启TCP_NODELAY并且关闭MSG_MORE的,这样做的目的是提高握手期间数据交互的延时,减少链接建立耗时,提高视频打开速度。在握手成功后,ZLMediaKit会关闭TCP_NODELAY并打开MSG_MORE;这样又能减少数据报文个数,提高网络利用率。
+网络编程中,大家应该都用过 send/sendto/write 函数,但是 writev/sendmsg 函数应该用的不多。ZLMediaKit 采用 sendmsg 函数来做批量数据发送,这样在网络不是很好或者服务器负载比较高时,可以明显减少系统调用(系统调用开销比较大)次数,提高程序性能。以下是代码片段:
-# 批量数据发送
-
-网络编程中,大家应该都用过send/sendto/write函数,但是writev/sendmsg函数应该用的不多。ZLMediaKit采用sendmsg函数来做批量数据发送,这样在网络不是很好或者服务器负载比较高时,可以明显减少系统调用(系统调用开销比较大)次数,提高程序性能。以下是代码片段:
-
-```c++
+```cpp
int BufferList::send_l(int fd, int flags,bool udp) {
int n;
do {
@@ -412,15 +405,15 @@ int BufferList::send_l(int fd, int flags,bool udp) {
}
```
-# 批量线程切换
+## 批量线程切换
-多线程模型下,流媒体服务器在做媒体数据分发时,肯定要做线程切换。线程切换的目的一是确保线程安全,防止多条线程同时操作某个对象或资源;二是可以充分利用多核算力,防止单线程成为转发性能瓶颈。ZLMediaKit在做媒体转发时,也同样使用到线程切换来实现多线程的数据分发。但是线程切换开销也比较大,如果线程切换次数太多,将严重影响服务器性能。
+多线程模型下,流媒体服务器在做媒体数据分发时,肯定要做线程切换。线程切换的目的一是确保线程安全,防止多条线程同时操作某个对象或资源;二是可以充分利用多核算力,防止单线程成为转发性能瓶颈。ZLMediaKit 在做媒体转发时,也同样使用到线程切换来实现多线程的数据分发。但是线程切换开销也比较大,如果线程切换次数太多,将严重影响服务器性能。
-现在我们假设一个场景:RTMP推流客户端A推送一个直播到服务器,这个直播比较火爆,假设有同时10K个用户正在观看这个直播,那么我们在分发一个RTMP数据包时是否需要最多进行10K次线程切换然后再发送数据?虽然ZLMediaKit的线程切换比较轻量,但是这样频繁的线程切换也是扛不住的。
+现在我们假设一个场景:RTMP 推流客户端 A 推送一个直播到服务器,这个直播比较火爆,假设有同时 10K 个用户正在观看这个直播,那么我们在分发一个 RTMP 数据包时是否需要最多进行 10K 次线程切换然后再发送数据?虽然 ZLMediaKit 的线程切换比较轻量,但是这样频繁的线程切换也是扛不住的。
-ZLMediaKit在处理这类问题时,采用批量线程切换来尽量减少线程切换次数。假如说这10K的用户分布在32个cpu核心上,那么ZLMediaKit最多进行32次线程切换,这样ZLMediaKit将大大减少线程切换次数,同时又能使用多线程来分发数据,大大提高网络吞吐量,以下是批量线程切换代码片段:
+ZLMediaKit 在处理这类问题时,采用批量线程切换来尽量减少线程切换次数。假如说这 10K 的用户分布在 32 个 cpu 核心上,那么 ZLMediaKit 最多进行 32 次线程切换,这样 ZLMediaKit 将大大减少线程切换次数,同时又能使用多线程来分发数据,大大提高网络吞吐量,以下是批量线程切换代码片段:
-```c++
+```cpp
void emitRead(const T &in){
LOCK_GUARD(_mtx_map);
for (auto &pr : _dispatcherMap) {
@@ -446,53 +439,35 @@ void emitRead(const T &in){
reader->onRead(in);
++it;
}
- }
+ }
```
+## 采用右值引用拷贝
+ZLMediaKit 中也尽量使用右值引用拷贝来规避内存拷贝,这里就不展开论述。
-# 采用右值引用拷贝
-
-ZLMediaKit中也尽量使用右值引用拷贝来规避内存拷贝,这里就不展开论述。
-
-# 其他特性
+## 其他特性
+### 优化及时推流打开率
+有些应用场景需要设备端开始推流,然后 APP 立即观看的应用场景。传统的 rtmp 服务器对此应用场景是未作任何优化的,如果 APP 播放请求在推流尚未建立之前到达,那么将导致 APP 播放失败,这样视频打开成功率就会降低,用户体验很不好。
-## 优化及时推流打开率
+ZLMediaKit 在针对该应用场景时,做了特别的优化;实现原理如下:
-有些应用场景需要设备端开始推流,然后APP立即观看的应用场景。传统的rtmp服务器对此应用场景是未作任何优化的,如果APP播放请求在推流尚未建立之前到达,那么将导致APP播放失败,这样视频打开成功率就会降低,用户体验很不好。
+1、收到播放请求时,立即检查是否已经存在的媒体源,如果存在返回播放成功,否则进入第 2 步。
-ZLMediaKit在针对该应用场景时,做了特别的优化;实现原理如下:
-
-1、收到播放请求时,立即检查是否已经存在的媒体源,如果存在返回播放成功,否则进入第2步。
-
-2、监听对应的媒体源注册事件,同时添加播放超时定时器,并且不回复播放器然后返回。逻辑将进入第3步或第4步。
+2、监听对应的媒体源注册事件,同时添加播放超时定时器,并且不回复播放器然后返回。逻辑将进入第 3 步或第 4 步。
3、媒体源注册成功,那么立即响应播放器播放成功,同时删除播放超时定时器,并移除媒体注册事件监听。
4、超时定时器触发,响应播放器播放失败,同时删除播放超时定时器,并移除媒体注册事件监听。
-使用ZLMediaKit作为流媒体服务器,可以APP播放请求和设备端推流同时进行。
-
-
-
-# 性能测试对比
-
-目前对ZLMediaKit做了一些性能测试,查看地址:[benchmark](../test/benchmark.md)
-
-在测试时发现,ZLMediaKit在负载比较低时,其单线程性能大概是SRS的50%,单条线程大概能支撑5K个播放器,导致这个性能差距的主要原因时由于采用本地轮回网络,网络状况为理想,那么sendmsg批量发送将不起优化左右;而SRS使用了合并写特性(就是缓存300毫秒左右的数据后一次性发送),可以减少系统调用次数;如果负载比较高,以及真实网络环境下,ZLMediaKit单线程性能应该跟SRS差距更小,我们在测试报告中也能发现在客户端比较多时,ZLMediaKit单线程线程性能有比较大的提升。
-
-由于ZLMediaKit支持多线程,可以充分利用多核CPU的性能,在多核服务器上,CPU已经不再是性能瓶颈,为了减少直播延时,目前合并写特性是默认关闭的,可以通过配置文件开启。
-
-
-
-
-
-
-
-
+使用 ZLMediaKit 作为流媒体服务器,可以 APP 播放请求和设备端推流同时进行。
+## 性能测试对比
+目前对 ZLMediaKit 做了一些性能测试,查看地址:[benchmark](../test/benchmark.md)
+在测试时发现,ZLMediaKit 在负载比较低时,其单线程性能大概是 SRS 的 50%,单条线程大概能支撑 5K 个播放器,导致这个性能差距的主要原因时由于采用本地轮回网络,网络状况为理想,那么 sendmsg 批量发送将不起优化左右;而 SRS 使用了合并写特性(就是缓存 300 毫秒左右的数据后一次性发送),可以减少系统调用次数;如果负载比较高,以及真实网络环境下,ZLMediaKit 单线程性能应该跟 SRS 差距更小,我们在测试报告中也能发现在客户端比较多时,ZLMediaKit 单线程线程性能有比较大的提升。
+由于 ZLMediaKit 支持多线程,可以充分利用多核 CPU 的性能,在多核服务器上,CPU 已经不再是性能瓶颈,为了减少直播延时,目前合并写特性是默认关闭的,可以通过配置文件开启。
diff --git a/src/zh/reference/documents/introduction_to_streaming_media_related_technologies.md b/src/zh/reference/documents/introduction_to_streaming_media_related_technologies.md
index 448a164..e492b9c 100644
--- a/src/zh/reference/documents/introduction_to_streaming_media_related_technologies.md
+++ b/src/zh/reference/documents/introduction_to_streaming_media_related_technologies.md
@@ -1,6 +1,7 @@
---
title: 流媒体相关技术介绍
---
+
## 1、流媒体简介
**流媒体**(streaming media)是指将一连串的媒体数据压缩后,经过网络分段发送数据,在网上即时传输影音以供观赏的一种技术与过程,此技术使得数据包得以像流水一样发送;如果不使用此技术,就必须在使用前下载整个媒体文件,这对于实时性要求比较高的场景而言,显然是不现实的,所以流媒体技术为此孕育而生。
@@ -17,35 +18,37 @@ title: 流媒体相关技术介绍
### 2.2 发展趋势
-由于一些互联网企业的入局,视频监控行业也在经历一系列的变局,譬如小米摄像头、360水滴摄像头的流行,也鞭策着传统的视频监控行业相关企业的变革(譬如海康威视推出的萤石云平台),虽然目前这些变革多数还局限于个人消费市场,但从长远来看,视频监控上云,是未来发展的大趋势。
+由于一些互联网企业的入局,视频监控行业也在经历一系列的变局,譬如小米摄像头、360 水滴摄像头的流行,也鞭策着传统的视频监控行业相关企业的变革(譬如海康威视推出的萤石云平台),虽然目前这些变革多数还局限于个人消费市场,但从长远来看,视频监控上云,是未来发展的大趋势。
基于云的视频监控解决方案由于其高质量、可靠性、安全性、便捷性以及较低的部署和维护成本而越来越受到人们的青睐。
-预计未来视频监控,将像目前流行的网络直播一样方便,用户安装好摄像头后,接入网络即可视频上云。使用者在浏览器或APP即可查看所有摄像头的实时监控以及历史录像,通过APP或绑定的手机号码,可以实时接收摄像头发送的事件通知(譬如入侵事件)。
+预计未来视频监控,将像目前流行的网络直播一样方便,用户安装好摄像头后,接入网络即可视频上云。使用者在浏览器或 APP 即可查看所有摄像头的实时监控以及历史录像,通过 APP 或绑定的手机号码,可以实时接收摄像头发送的事件通知(譬如入侵事件)。
### 2.3 技术难点
-由于历史原因,传统的视频监控行业技术栈多采用私有协议SDK、onvif/rtsp等协议栈。这些协议目前对浏览器而言都不友好,在以前IE浏览器还流行的时期,可以通过ocx插件的方式来对接这些协议,但是随着IE的没落以及目前流行的chrome、火狐浏览器对原生插件的愈加不友好,通过插件的方式来实现访问监控视频的方式将愈发困难。如果要在chrome、火狐浏览器上访问监控视频,目前有以下几种方案可行:
+由于历史原因,传统的视频监控行业技术栈多采用私有协议 SDK、onvif/rtsp 等协议栈。这些协议目前对浏览器而言都不友好,在以前 IE 浏览器还流行的时期,可以通过 ocx 插件的方式来对接这些协议,但是随着 IE 的没落以及目前流行的 chrome、火狐浏览器对原生插件的愈加不友好,通过插件的方式来实现访问监控视频的方式将愈发困难。如果要在 chrome、火狐浏览器上访问监控视频,目前有以下几种方案可行:
+
+- rtmp
+
+ 目前主流的 chrome 和火狐浏览器都还支持 flash 插件,所以目前在浏览器上还可以通过 rtmp 方式来访问监控视频。但是由于随着 html5 的普及以及 flash 的停止更新,预计可预见的未来,rtmp 技术将随着 flash 一起行将就木(谷歌宣布 chrome 浏览器 2020 年 12 月将不再支持 flash player)。
-- rtmp
-
-目前主流的chrome和火狐浏览器都还支持flash插件,所以目前在浏览器上还可以通过rtmp方式来访问监控视频。但是由于随着html5的普及以及flash的停止更新,预计可预见的未来,rtmp技术将随着flash一起行将就木(谷歌宣布chrom浏览器2020年12月将不再支持flash player)。
- http-flv
-
-http-flv直播的方式是一种比较新颖的方式,该技术基于html5,可以通过无插件的方式实现视频直播,而且由于rtmp负载可以平滑的转换成http-flv协议,所以正在逐渐取代rtmp成为新的直播技术标准,目前各大直播网站(譬如斗鱼直播,bilibili等)也陆续从rtmp切换成该技术。
- 但是由于浏览器的限制,不能同时打开过多(chrome限制6个)的同域名下的直播窗口,所以该技术也不太适合多路同时打开(譬如9宫格视频)的视频监控领域。而且由于Adobe的不作为,flv容器格式停止了更新,对H265的支持遥遥无期。
+
+http-flv 直播的方式是一种比较新颖的方式,该技术基于 html5,可以通过无插件的方式实现视频直播,而且由于 rtmp 负载可以平滑的转换成 http-flv 协议,所以正在逐渐取代 rtmp 成为新的直播技术标准,目前各大直播网站(譬如斗鱼直播,bilibili 等)也陆续从 rtmp 切换成该技术。
+但是由于浏览器的限制,不能同时打开过多(chrome 限制 6 个)的同域名下的直播窗口,所以该技术也不太适合多路同时打开(譬如 9 宫格视频)的视频监控领域。而且由于 Adobe 的不作为,flv 容器格式停止了更新,对 H265 的支持遥遥无期。
- ws-flv
-
-ws-flv直播技术基本与http-flv一致,无非是传输`介质`换成了websocket协议,除了解除了http-flv不能同时打开过多同域名下的直播窗口的限制,其他技术特性、参数基本与http-flv一致。目前看,ws-flv既适合视频监控(可以同时打开多路监控视频)也适合视频直播行业,是rtmp很高的升级替代方案。
+
+ ws-flv 直播技术基本与 http-flv 一致,无非是传输`介质`换成了 websocket 协议,除了解除了 http-flv 不能同时打开过多同域名下的直播窗口的限制,其他技术特性、参数基本与 http-flv 一致。目前看,ws-flv 既适合视频监控(可以同时打开多路监控视频)也适合视频直播行业,是 rtmp 很高的升级替代方案。
- webrtc
-
-webrtc是谷歌主导的视频通话技术标准,目前各大主流浏览器都兼容该标准。通过该技术,用户可以在浏览器上实现无插件的视频通话,该技术也可以用于实现低延时的视频直播。目前业界也有很多基于webrtc的应用和产品,但是很多局限于视频聊天等低延时交互式场景,在视频监控领域,目前还尚未流行。而且该技术栈目前还在持续更新,技术难点太多,要与视频监控领域融合还需时日。
+
+ webrtc 是谷歌主导的视频通话技术标准,目前各大主流浏览器都兼容该标准。通过该技术,用户可以在浏览器上实现无插件的视频通话,该技术也可以用于实现低延时的视频直播。目前业界也有很多基于 webrtc 的应用和产品,但是很多局限于视频聊天等低延时交互式场景,在视频监控领域,目前还尚未流行。而且该技术栈目前还在持续更新,技术难点太多,要与视频监控领域融合还需时日。
+
- hls
-
-hls协议是苹果公司主导的技术标准,该技术标准兼容性最佳。不仅桌面浏览器,包括手机浏览器甚至是手机QQ、手机微信都支持该直播协议。
- 但是该协议延时比较大,不太适合视频监控等对延时要求很敏感的行业。不过最近苹果公司新推出低延时hls直播标准,预计hls标准将抢占更大的市场份额。
+
+ hls 协议是苹果公司主导的技术标准,该技术标准兼容性最佳。不仅桌面浏览器,包括手机浏览器甚至是手机 QQ、手机微信都支持该直播协议。
+ 但是该协议延时比较大,不太适合视频监控等对延时要求很敏感的行业。不过最近苹果公司新推出低延时 hls 直播标准,预计 hls 标准将抢占更大的市场份额。
以上直播技术标准目前都不完全契合视频监控行业的需求,如果要达到比较好的用户体验,通常以上技术混合使用。
@@ -54,42 +57,42 @@ hls协议是苹果公司主导的技术标准,该技术标准兼容性最佳
### 3.1 视频直播的现状和挑战
视频直播是近几年才兴起的产业,特别是随着游戏直播、手机直播的流行,视频直播已经司空见惯,进入了每个人的视野。
-随着阿里、腾讯等云平台的入局,OBS,SRS等优秀软件的开源,视频加速CDN技术的成熟,打赏、广告等商业模式的落地,目前视频直播产业链已经非常成熟,业界也诞生了斗鱼、虎牙、映客、花椒等知名直播平台。
+随着阿里、腾讯等云平台的入局,OBS,SRS 等优秀软件的开源,视频加速 CDN 技术的成熟,打赏、广告等商业模式的落地,目前视频直播产业链已经非常成熟,业界也诞生了斗鱼、虎牙、映客、花椒等知名直播平台。
-目前而言,这些直播平台使用的技术栈基本都是rtmp,但是由于flash技术即将被淘汰,所以直播行业也将迎来一些变局以及挑战。
-现在,基本上所有的直播平台,在web端,都已经或正在往http-flv方案转型。由于flv与rtmp同出一门(都是Adobe公司产品),负载格式一致,方案升级改造平滑可靠,http-flv替代rtmp具有天然的优势,相信将来http-flv能很好的挑起rtmp的大梁。
+目前而言,这些直播平台使用的技术栈基本都是 rtmp,但是由于 flash 技术即将被淘汰,所以直播行业也将迎来一些变局以及挑战。
+现在,基本上所有的直播平台,在 web 端,都已经或正在往 http-flv 方案转型。由于 flv 与 rtmp 同出一门(都是 Adobe 公司产品),负载格式一致,方案升级改造平滑可靠,http-flv 替代 rtmp 具有天然的优势,相信将来 http-flv 能很好的挑起 rtmp 的大梁。
### 3.2 发展趋势
-视频直播目前从内容上来讲,涵盖了游戏、美女、户外、娱乐、体育等直播;从设备上来讲,涵盖了PC、手机、web、电视等客户端,市场上也诞生了斗鱼这样的头部企业。从目前来看,视频直播行业市场格局已经比较稳固,进入了平稳发展期。
+视频直播目前从内容上来讲,涵盖了游戏、美女、户外、娱乐、体育等直播;从设备上来讲,涵盖了 PC、手机、web、电视等客户端,市场上也诞生了斗鱼这样的头部企业。从目前来看,视频直播行业市场格局已经比较稳固,进入了平稳发展期。
从技术上来讲,直播行业也将迎来一些变革。
-一是rtmp技术随着flash的一起淘汰,web端rtmp播放器将成为历史。
-二是随着webrtc的强势流行,直播技术栈可能与webrtc融合。
-三是苹果主导的低延时hls的推出,可能最终有大一统之势。
+一是 rtmp 技术随着 flash 的一起淘汰,web 端 rtmp 播放器将成为历史。
+二是随着 webrtc 的强势流行,直播技术栈可能与 webrtc 融合。
+三是苹果主导的低延时 hls 的推出,可能最终有大一统之势。
-不过近期来看,http-flv是rtmp的最佳替代方案,但是和rtmp一样,也有不支持H265的短板,而且移动端浏览器对此支持并不完善,所以该方案在将来有大概率会被其他方案替代。
+不过近期来看,http-flv 是 rtmp 的最佳替代方案,但是和 rtmp 一样,也有不支持 H265 的短板,而且移动端浏览器对此支持并不完善,所以该方案在将来有大概率会被其他方案替代。
### 3.3 技术难点
直播行业相对视频监控行业来说,商业化程度更高,更面向于普通消费者,用户规模更大,产业链也更加成熟。但是由于利益格局的划分、巨头间标准制定的角力,目前直播的技术标准和用户体验是割裂的。
-在桌面web端,之前直播技术由Adobe旗下的flash/rtmp技术主导,不过由于Adobe的不作为,以及谷歌苹果等公司的抵制,flash已经进入死亡倒计时。目前来看,http-flv已经接手rtmp的大旗,成为了新的事实上的桌面web端直播标准。但是http-flv由于其不支持H265的短板(Adobe官方可能永远也不会支持H265),其地位也并不稳固,现在也有公司正在尝试使用webrtc进行视频直播,但是由于该技术跨界太大,其技术栈又太庞杂,整个上下游产业链也并不完善,目前在直播界,还未看见大规模采用该直播技术的方案实施。
+在桌面 web 端,之前直播技术由 Adobe 旗下的 flash/rtmp 技术主导,不过由于 Adobe 的不作为,以及谷歌苹果等公司的抵制,flash 已经进入死亡倒计时。目前来看,http-flv 已经接手 rtmp 的大旗,成为了新的事实上的桌面 web 端直播标准。但是 http-flv 由于其不支持 H265 的短板(Adobe 官方可能永远也不会支持 H265),其地位也并不稳固,现在也有公司正在尝试使用 webrtc 进行视频直播,但是由于该技术跨界太大,其技术栈又太庞杂,整个上下游产业链也并不完善,目前在直播界,还未看见大规模采用该直播技术的方案实施。
-在手机APP端,由于播放技术自己可以主导,也由于历史沿革原因,目前一般沿用rtmp技术方案(需要指出的是微信小程序也支持rtmp播放器),用户体验比较好,延时一般3秒或以下。
+在手机 APP 端,由于播放技术自己可以主导,也由于历史沿革原因,目前一般沿用 rtmp 技术方案(需要指出的是微信小程序也支持 rtmp 播放器),用户体验比较好,延时一般 3 秒或以下。
-在移动web端,可采用的直播方案更少,目前基本只能采用苹果公司主导的hls方案,但是由于hls的技术特性,延时非常大(一般5秒以上,最大可达10秒以上),其观看体验跟手机APP、桌面web端是严重割裂的。
+在移动 web 端,可采用的直播方案更少,目前基本只能采用苹果公司主导的 hls 方案,但是由于 hls 的技术特性,延时非常大(一般 5 秒以上,最大可达 10 秒以上),其观看体验跟手机 APP、桌面 web 端是严重割裂的。
-通过我们上述的分析看出,目前直播技术方案,在每种端都不一样,用户体验也差距巨大,目前并没有一种多平台支持、令人满意的通用解决方案。目前要实现一个完善的直播产品,最少要采用包括rtmp/http-flv/hls这3种技术方案,而且这三种技术方案目前也并不能让人满意(rtmp/http-flv不支持H265,hls延时高)。
+通过我们上述的分析看出,目前直播技术方案,在每种端都不一样,用户体验也差距巨大,目前并没有一种多平台支持、令人满意的通用解决方案。目前要实现一个完善的直播产品,最少要采用包括 rtmp/http-flv/hls 这 3 种技术方案,而且这三种技术方案目前也并不能让人满意(rtmp/http-flv 不支持 H265,hls 延时高)。
## 4、我们的解决方案以及优势
-目前我们的流媒体服务框架支持rtsp/rtmp推流客户端,rtsp/rtmp/http-flv/ws-flv/hls播放客户端,并且可以无缝把rtsp/rtmp推流转换成上述4种播放协议,同时我们也支持mp4录制存档,必要的时候也可以从mp4文件加载成直播流。
+目前我们的流媒体服务框架支持 rtsp/rtmp 推流客户端,rtsp/rtmp/http-flv/ws-flv/hls 播放客户端,并且可以无缝把 rtsp/rtmp 推流转换成上述 4 种播放协议,同时我们也支持 mp4 录制存档,必要的时候也可以从 mp4 文件加载成直播流。
-除了上述功能之外,我们还支持拉流rtsp/rtmp代理成rtsp/rtmp/http-flv/ws-flv/hls,也支持把直播rtsp/rtmp流推送到其他的服务器。
+除了上述功能之外,我们还支持拉流 rtsp/rtmp 代理成 rtsp/rtmp/http-flv/ws-flv/hls,也支持把直播 rtsp/rtmp 流推送到其他的服务器。
-另外,我们还提供丰富的http api 以及 http hook api,通过这些api,我们可以与其他业务服务器一起,打造丰富的业务逻辑。
+另外,我们还提供丰富的 http api 以及 http hook api,通过这些 api,我们可以与其他业务服务器一起,打造丰富的业务逻辑。
-我们的流媒体框架支持linux、macos、ios、android、windows全平台,既可以作为商用的流媒体服务器,也可以移植到嵌入式设备中,作为基础流媒体服务组件。
+我们的流媒体框架支持 linux、macos、ios、android、windows 全平台,既可以作为商用的流媒体服务器,也可以移植到嵌入式设备中,作为基础流媒体服务组件。
-代码采用C++11标准打造,避免使用裸指针,稳定可靠,采用epoll多路复用、线程池、异步网络IO模式开发,并发性能优越,已经经受住了长期的高并发验证考验。同时针对及时推流的特征,做了特别的优化,可以减少视频打开延时、提高画面打开成功率,让用户获取画面秒开,延时极低的体验。
+代码采用 C++11 标准打造,避免使用裸指针,稳定可靠,采用 epoll 多路复用、线程池、异步网络 IO 模式开发,并发性能优越,已经经受住了长期的高并发验证考验。同时针对及时推流的特征,做了特别的优化,可以减少视频打开延时、提高画面打开成功率,让用户获取画面秒开,延时极低的体验。
diff --git a/src/zh/reference/documents/rtsp_push_process.md b/src/zh/reference/documents/rtsp_push_process.md
index 4985258..85d4c2d 100644
--- a/src/zh/reference/documents/rtsp_push_process.md
+++ b/src/zh/reference/documents/rtsp_push_process.md
@@ -1,9 +1,12 @@
---
title: RTSP推流流程
---
-# 1、客户端发送ANNOUNCE命令
-此步骤主要传输SDP,一般而言在这个命令之前还需要OPTIONS命令侦探服务器是否支持推流协议,但是为了减少交互次数,可以直接发送ANNOUNCE命令,如果不支持,服务器自然响应错误代码。
-```
+
+# 1、客户端发送 ANNOUNCE 命令
+
+此步骤主要传输 SDP,一般而言在这个命令之前还需要 OPTIONS 命令侦探服务器是否支持推流协议,但是为了减少交互次数,可以直接发送 ANNOUNCE 命令,如果不支持,服务器自然响应错误代码。
+
+```http
ANNOUNCE rtsp://10.0.9.130:554/live/2.sdp RTSP/1.0
CSeq: 1
User-Agent: EasyPusher v1.2.16.1105
@@ -31,9 +34,11 @@ a=fmtp:97 streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength
a=control:streamid=1
```
-# 2、服务器响应ANNOUNCE命令
-服务器如果解析SDP成功,那么会返回200代码表明成功
-```
+# 2、服务器响应 ANNOUNCE 命令
+
+服务器如果解析 SDP 成功,那么会返回 200 代码表明成功
+
+```http
RTSP/1.0 200 OK
CSeq: 1
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -41,20 +46,23 @@ Server: ZLMediaKit-4.0(build in Mar 26 2019 17:01:17)
Session: KPUZ49ejotyD
```
-# 3、客户端发送SETUP命令
-此命令作用是协商rtp传输方式,可选tcp和udp方式,为了简便,建议使用tcp方式推流
-需要指出的是,如果sdp中有多个track(例如音视频都有),那么SETUP命令交互会有多次
+# 3、客户端发送 SETUP 命令
-```
+此命令作用是协商 rtp 传输方式,可选 tcp 和 udp 方式,为了简便,建议使用 tcp 方式推流
+需要指出的是,如果 sdp 中有多个 track(例如音视频都有),那么 SETUP 命令交互会有多次
+
+```http
SETUP rtsp://10.0.9.130:554/live/2.sdp/streamid=0 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;mode=record;interleaved=0-1
CSeq: 2
User-Agent: EasyPusher v1.2.16.1105
```
-# 4、服务器响应SETUP命令
-服务器返回协商好的interleaved,其他自便
-```
+# 4、服务器响应 SETUP 命令
+
+服务器返回协商好的 interleaved,其他自便
+
+```http
RTSP/1.0 200 OK
CSeq: 2
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -65,10 +73,12 @@ x-Dynamic-Rate: 1
x-Transport-Options: late-tolerance=1.400000
```
-# 5、客户端发送RECORD命令
-相当于播放时的play命令,同步命令,让服务器准备好。
-请注意,为了节省篇幅,该命令前省略了一次SETUP交互
-```
+# 5、客户端发送 RECORD 命令
+
+相当于播放时的 play 命令,同步命令,让服务器准备好。
+请注意,为了节省篇幅,该命令前省略了一次 SETUP 交互
+
+```http
RECORD rtsp://10.0.9.130:554/live/2.sdp RTSP/1.0
Range: npt=0.000-
CSeq: 4
@@ -76,9 +86,11 @@ User-Agent: EasyPusher v1.2.16.1105
Session: KPUZ49ejotyD
```
-# 6、服务器响应RECORD命令,可以开始推流!
-服务器响应RECORD命令后,推流客户端就可以源源不断发送RTP包了
-```
+# 6、服务器响应 RECORD 命令,可以开始推流!
+
+服务器响应 RECORD 命令后,推流客户端就可以源源不断发送 RTP 包了
+
+```http
RTSP/1.0 200 OK
CSeq: 4
Date: Tue, Mar 26 2019 09:10:10 GMT
@@ -86,9 +98,3 @@ RTP-Info: url=rtsp://10.0.9.130:554/live/2.sdp/streamid=0,url=rtsp://10.0.9.130:
Server: ZLMediaKit-4.0(build in Mar 26 2019 17:01:17)
Session: KPUZ49ejotyD
```
-
-
-
-
-
-
diff --git a/src/zh/reference/documents/the_nature_of_live_broadcast_delay.md b/src/zh/reference/documents/the_nature_of_live_broadcast_delay.md
index 63fdf64..3508787 100644
--- a/src/zh/reference/documents/the_nature_of_live_broadcast_delay.md
+++ b/src/zh/reference/documents/the_nature_of_live_broadcast_delay.md
@@ -1,16 +1,17 @@
---
title: 直播延时的本质
---
+
- 1、所谓直播就是正在发生的事情,流逝多少时间产生多少数据。
-- 2、那么直播为什么会有延时?本质是,直播为了提升体验,会给缓存一部分历史数据(比如说为了提高画面打开速度做GOP缓存)。
+- 2、那么直播为什么会有延时?本质是,直播为了提升体验,会给缓存一部分历史数据(比如说为了提高画面打开速度做 GOP 缓存)。
-- 3、那是不是没有GOP缓存就不会有延时呢?答案是错误的,因为不仅仅你的服务器有缓存,播放器也有缓存。播放器在点击`开始播放`到`出现画面`会有**时间差**,那么为什么播放器要这么做?原因是播放器为了提高播放流畅度,做了缓存。直播数据传到播放器我们可以认为是一根水管,这跟水管水量时大时小,有时干脆断流,如果不用`桶`缓存一下,那么画面会卡顿。
+- 3、那是不是没有 GOP 缓存就不会有延时呢?答案是错误的,因为不仅仅你的服务器有缓存,播放器也有缓存。播放器在点击`开始播放`到`出现画面`会有**时间差**,那么为什么播放器要这么做?原因是播放器为了提高播放流畅度,做了缓存。直播数据传到播放器我们可以认为是一根水管,这跟水管水量时大时小,有时干脆断流,如果不用`桶`缓存一下,那么画面会卡顿。
-- 4、假定我们削掉服务器和播放器所有的缓存,那么是不是就没有延时呢?Too yong too simple!记住,**缓存是永远无法消灭的**。假定网络是根水管,我们掐住它5秒,然后再放开手,那么这5秒的数据会消失吗?并不会!直播是正在发生的事情,它会源源不断产生`水量`,会把水管涨粗,在这5秒内,播放器就得干等数据,等网络恢复了,那么这5秒的数据会一股脑怼给播放器,然后又是接着的源源不断过来的直播数据,这样播放器就多了5秒的数据,而这多出来5秒的数据要么直接丢弃要么加快播放速度,否则永远都不会凭空消灭掉。
+- 4、假定我们削掉服务器和播放器所有的缓存,那么是不是就没有延时呢?Too yong too simple!记住,**缓存是永远无法消灭的**。假定网络是根水管,我们掐住它 5 秒,然后再放开手,那么这 5 秒的数据会消失吗?并不会!直播是正在发生的事情,它会源源不断产生`水量`,会把水管涨粗,在这 5 秒内,播放器就得干等数据,等网络恢复了,那么这 5 秒的数据会一股脑怼给播放器,然后又是接着的源源不断过来的直播数据,这样播放器就多了 5 秒的数据,而这多出来 5 秒的数据要么直接丢弃要么加快播放速度,否则永远都不会凭空消灭掉。
- 5、很遗憾的告诉你,几乎所有标准播放器,都不会直接丢数据或加快播放速度。
-- 6、那细心的小伙伴会问我,为什么UDP直播延时更低?原因是UDP这根`管子`上有很多破洞,水量太大了直接漏了,表现形式就是数据直接丢了,那么播放器就得花屏了。
+- 6、那细心的小伙伴会问我,为什么 UDP 直播延时更低?原因是 UDP 这根`管子`上有很多破洞,水量太大了直接漏了,表现形式就是数据直接丢了,那么播放器就得花屏了。
-- 7、TCP水管涨粗可以理解为网络链路缓存的增加(路由器缓存增加),如果滞留的水量太大了怎么办?那么先是撑满网络链路缓存,然后撑满发送端Socket缓存,然后撑满发送端应用逻辑缓存,如果还放不下,那么对不起,服务器只能掐断TCP了。
+- 7、TCP 水管涨粗可以理解为网络链路缓存的增加(路由器缓存增加),如果滞留的水量太大了怎么办?那么先是撑满网络链路缓存,然后撑满发送端 Socket 缓存,然后撑满发送端应用逻辑缓存,如果还放不下,那么对不起,服务器只能掐断 TCP 了。
diff --git a/src/zh/reference/resources/README.md b/src/zh/reference/resources/README.md
index 975262a..bd59a9f 100644
--- a/src/zh/reference/resources/README.md
+++ b/src/zh/reference/resources/README.md
@@ -3,4 +3,5 @@ title: 相关资源
icon: font-awesome
index: true
---
+
diff --git a/src/zh/reference/resources/dependency.md b/src/zh/reference/resources/dependency.md
index d0303e3..fa8e3d5 100644
--- a/src/zh/reference/resources/dependency.md
+++ b/src/zh/reference/resources/dependency.md
@@ -3,45 +3,36 @@ title: 代码依赖与版权声明
icon: code
---
-## 一、zlmediakit依赖的库列表
-
-
-| 依赖组件 | 协议类型 | 备注 | 项目地址 |
-| :------------------: | :----------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
-| ZLToolKit | MIT | 强依赖,ZLToolKit也部分依赖某些开源代码 | https://github.com/ZLMediaKit/ZLToolKit |
-| ireader/media-server | MIT | 默认依赖,编译时指定ENABLE_HLS,ENABLE_MP4,ENABLE_RTPPROXY为关闭时可以去除依赖 | https://github.com/ireader/media-server |
-| jsoncpp | MIT | MediaServer依赖 | https://github.com/open-source-parsers/jsoncpp |
-| openssl | Apache-2.0 | 开启ssl和webrtc相关功能时依赖,编译时指定ENABLE_OPENSSL,ENABLE_WEBRTC为关闭时可以去除依赖 | https://github.com/openssl/openssl |
-| srtp | 类MIT | 开启webrtc相关功能时依赖,编译时指定ENABLE_WEBRTC为关闭时可以去除依赖 | https://github.com/cisco/libsrtp |
-| usrsctp | BSD-3-Clause | 开启webrtc datachannel相关功能时依赖,编译时指定ENABLE_SCTP为关闭时可以去除依赖 | https://github.com/sctplab/usrsctp |
-| mediasoup | ISC | 部分webrtc源码提取自mediasoup,编译时指定ENABLE_WEBRTC为关闭时可以去除依赖 | https://github.com/versatica/mediasoup |
-| ffmpeg | GPL/LGPL | 转码分支与mk_api有轻微依赖,编译时指定ENABLE_FFMPEG为关闭时可以去除依赖,默认关闭 | https://github.com/FFmpeg/FFmpeg |
-| wepoll | 类MIT | Windows下编译ENABLE_WPOLL为开始时依赖,默认关闭 | https://github.com/piscisaureus/wepoll |
-| SPSParser | | sps/pps相关解析代码,来自朋友,经过修改,应该最开始提取自ffmpeg,版权存疑 | https://github.com/ZLMediaKit/ZLMediaKit/blob/master/src/Extension/SPSParser.h |
+## 一、zlmediakit 依赖的库列表
+
+| 依赖组件 | 协议类型 | 备注 | 项目地址 |
+| :------------------: | :----------: | :---------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |
+| ZLToolKit | MIT | 强依赖,ZLToolKit 也部分依赖某些开源代码 | https://github.com/ZLMediaKit/ZLToolKit |
+| ireader/media-server | MIT | 默认依赖,编译时指定 ENABLE_HLS,ENABLE_MP4,ENABLE_RTPPROXY 为关闭时可以去除依赖 | https://github.com/ireader/media-server |
+| jsoncpp | MIT | MediaServer 依赖 | https://github.com/open-source-parsers/jsoncpp |
+| openssl | Apache-2.0 | 开启 ssl 和 webrtc 相关功能时依赖,编译时指定 ENABLE_OPENSSL,ENABLE_WEBRTC 为关闭时可以去除依赖 | https://github.com/openssl/openssl |
+| srtp | 类 MIT | 开启 webrtc 相关功能时依赖,编译时指定 ENABLE_WEBRTC 为关闭时可以去除依赖 | https://github.com/cisco/libsrtp |
+| usrsctp | BSD-3-Clause | 开启 webrtc datachannel 相关功能时依赖,编译时指定 ENABLE_SCTP 为关闭时可以去除依赖 | https://github.com/sctplab/usrsctp |
+| mediasoup | ISC | 部分 webrtc 源码提取自 mediasoup,编译时指定 ENABLE_WEBRTC 为关闭时可以去除依赖 | https://github.com/versatica/mediasoup |
+| ffmpeg | GPL/LGPL | 转码分支与 mk_api 有轻微依赖,编译时指定 ENABLE_FFMPEG 为关闭时可以去除依赖,默认关闭 | https://github.com/FFmpeg/FFmpeg |
+| wepoll | 类 MIT | Windows 下编译 ENABLE_WPOLL 为开始时依赖,默认关闭 | https://github.com/piscisaureus/wepoll |
+| SPSParser | | sps/pps 相关解析代码,来自朋友,经过修改,应该最开始提取自 ffmpeg,版权存疑 | https://github.com/ZLMediaKit/ZLMediaKit/blob/master/src/Extension/SPSParser.h |
## 二、其他依赖
-- 开启编译test_player测试程序时依赖sdl。
-- 开启x264/faac相关功能时依赖libx264与libfacc,默认关闭。
-- 开启jemalloc时依赖jemalloc,默认关闭。
-- 开始mysql连接池功能时依赖libmysql-clinet,默认关闭。
+- 开启编译 test_player 测试程序时依赖 sdl。
+- 开启 x264/faac 相关功能时依赖 libx264 与 libfacc,默认关闭。
+- 开启 jemalloc 时依赖 jemalloc,默认关闭。
+- 开始 mysql 连接池功能时依赖 libmysql-clinet,默认关闭。
+
+## 三、ZLToolkit 相关依赖
-## 三、ZLToolkit相关依赖
-- [getopt](https://github.com/ZLMediaKit/ZLToolKit/tree/master/src/win32) windows下命令行解析工具,其他平台不依赖。
-- [uv_errno](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/uv_errno.h) 部分错误处理代码来自libuv。
-- [strptime_win](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/strptime_win.cpp) windows下strptime移植函数代码,来源网络,出处已不可考。
+- [getopt](https://github.com/ZLMediaKit/ZLToolKit/tree/master/src/win32) windows 下命令行解析工具,其他平台不依赖。
+- [uv_errno](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/uv_errno.h) 部分错误处理代码来自 libuv。
+- [strptime_win](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/strptime_win.cpp) windows 下 strptime 移植函数代码,来源网络,出处已不可考。
- [mini](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/mini.h) 来源于[github](https://github.com/r-lyeh-archived/mINI),经过整理和修改。
- [function_traits](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/function_traits.h)来源自网络,应该出自祁宇。
-- [base64](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/base64.h) 来源自网络,经过修改,应该出自ffmpeg。
+- [base64](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/base64.h) 来源自网络,经过修改,应该出自 ffmpeg。
- [SHA1](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/SHA1.h) 整理自[GitHub](https://github.com/vog/sha1)
-- [MD5](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/MD5.h) 整理自GitHub,已无法找到原始出处。
-
-
-
-
-
-
-
-
-
+- [MD5](https://github.com/ZLMediaKit/ZLToolKit/blob/master/src/Util/MD5.h) 整理自 GitHub,已无法找到原始出处。
diff --git a/src/zh/reference/resources/rtmp_support_for_h265_and_opus.md b/src/zh/reference/resources/rtmp_support_for_h265_and_opus.md
index 392b192..d3c10e1 100644
--- a/src/zh/reference/resources/rtmp_support_for_h265_and_opus.md
+++ b/src/zh/reference/resources/rtmp_support_for_h265_and_opus.md
@@ -1,18 +1,19 @@
---
title: RTMP对H265和OPUS的支持
---
+
## 背景
-rtmp/flv是直播行业事实上的标准,这两者在国内直播领域应用非常广泛。在浏览器上要实现无插件的低延时直播播放,基本绕不开rtmp/flv.
-由于rtmp/flv是Adobe设计的私有协议,原生是不支持H265(视频监控应用广泛)和opus(RTC应用广泛)的,而目前视频监控、RTC相关行业都有使用直播基础设施的需求,所以对rtmp进行修改,使其添加对H265和opus的支持比较重要。
-## 实现方式
-rtmp通过codec id来判断编码格式,同时通过message type来区分数据类型(包括音频包、视频包),所以音视频的codec_id是可以相同的(相同类型不冲突即可);
-例如H264的codec id为7,G711A的codec id也为7。
-目前国内默认定义H265的codec id为**12**(由金山云首先[实现并公布](https://github.com/ksvc/FFmpeg/wiki)).
-而对opus的rtmp扩展目前还未有广泛共识,作者在与相关人士讨论后,协商定义其codec id为**13**,目前已经实现了对FFmpeg(基于最新版本)的修改,添加了对[h265/opus的rtmp扩展](https://gitee.com/xia-chu/FFmpeg).
+rtmp/flv 是直播行业事实上的标准,这两者在国内直播领域应用非常广泛。在浏览器上要实现无插件的低延时直播播放,基本绕不开 rtmp/flv.
+由于 rtmp/flv 是 Adobe 设计的私有协议,原生是不支持 H265(视频监控应用广泛)和 opus(RTC 应用广泛)的,而目前视频监控、RTC 相关行业都有使用直播基础设施的需求,所以对 rtmp 进行修改,使其添加对 H265 和 opus 的支持比较重要。
-## 服务器实现
-ZLMediaKit已经实现了rtsp/rtmp/mp4/hls对h265/opus的全面支持, 欢迎各位测试使用。
+## 实现方式
+rtmp 通过 codec id 来判断编码格式,同时通过 message type 来区分数据类型(包括音频包、视频包),所以音视频的 codec_id 是可以相同的(相同类型不冲突即可);
+例如 H264 的 codec id 为 7,G711A 的 codec id 也为 7。
+目前国内默认定义 H265 的 codec id 为**12**(由金山云首先[实现并公布](https://github.com/ksvc/FFmpeg/wiki)).
+而对 opus 的 rtmp 扩展目前还未有广泛共识,作者在与相关人士讨论后,协商定义其 codec id 为**13**,目前已经实现了对 FFmpeg(基于最新版本)的修改,添加了对[h265/opus 的 rtmp 扩展](https://gitee.com/xia-chu/FFmpeg).
+## 服务器实现
+ZLMediaKit 已经实现了 rtsp/rtmp/mp4/hls 对 h265/opus 的全面支持, 欢迎各位测试使用。
diff --git a/src/zh/reference/resources/video_conferencing_related_resources.md b/src/zh/reference/resources/video_conferencing_related_resources.md
index 9013667..3009920 100644
--- a/src/zh/reference/resources/video_conferencing_related_resources.md
+++ b/src/zh/reference/resources/video_conferencing_related_resources.md
@@ -1,13 +1,14 @@
---
title: 视频会议相关资源
---
+
- [Random Tech Talking](https://www.bilibili.com/video/BV1AK411R7NG/)
- - 相关素材:[webrtc over tcp](https://user-images.githubusercontent.com/11495632/204230234-04da9d84-ffc7-4d32-bda3-04c72474205f.png)、[webrtc over udp](https://user-images.githubusercontent.com/11495632/204230272-13448d78-b6da-40f2-94b9-da517fa5cc0b.png)、[webrtc时序图](https://user-images.githubusercontent.com/11495632/204230325-1b395c6f-c094-414d-9d4e-8ea04120eed6.png)。
-- WebRTC
- - [ZLMediaKit源代码讲解1](https://www.bilibili.com/video/BV1kq4y1u7cN/)
- - [ZLMediaKit源代码讲解2](https://www.bilibili.com/video/BV1SR4y1t7V4/)
- - [ZLMediaKit webrtc使用演示](https://www.bilibili.com/video/BV1Eg411N7TJ/)
- - [ZLMediaKit webrtc实现](https://www.bilibili.com/video/BV1uL4y1i7KP/)
+ - 相关素材: [webrtc over tcp](https://user-images.githubusercontent.com/11495632/204230234-04da9d84-ffc7-4d32-bda3-04c72474205f.png)、[webrtc over udp](https://user-images.githubusercontent.com/11495632/204230272-13448d78-b6da-40f2-94b9-da517fa5cc0b.png)、[webrtc 时序图](https://user-images.githubusercontent.com/11495632/204230325-1b395c6f-c094-414d-9d4e-8ea04120eed6.png)。
+- WebRTC
+ - [ZLMediaKit 源代码讲解 1](https://www.bilibili.com/video/BV1kq4y1u7cN/)
+ - [ZLMediaKit 源代码讲解 2](https://www.bilibili.com/video/BV1SR4y1t7V4/)
+ - [ZLMediaKit webrtc 使用演示](https://www.bilibili.com/video/BV1Eg411N7TJ/)
+ - [ZLMediaKit webrtc 实现](https://www.bilibili.com/video/BV1uL4y1i7KP/)
diff --git a/src/zh/reference/resources/zltoolkit_source_code_study_notes.md b/src/zh/reference/resources/zltoolkit_source_code_study_notes.md
index e4ed2e4..0d07b41 100644
--- a/src/zh/reference/resources/zltoolkit_source_code_study_notes.md
+++ b/src/zh/reference/resources/zltoolkit_source_code_study_notes.md
@@ -1,4 +1,5 @@
---
title: ZLToolKit源码学习笔记
---
-[zltoolkit源码分析](https://blog.csdn.net/youlezhe/category_11460699.html)
+
+[zltoolkit 源码分析](https://blog.csdn.net/youlezhe/category_11460699.html)
diff --git a/src/zh/reference/test/benchmark.md b/src/zh/reference/test/benchmark.md
index cecd3b6..e2e5348 100644
--- a/src/zh/reference/test/benchmark.md
+++ b/src/zh/reference/test/benchmark.md
@@ -1,47 +1,53 @@
---
title: Benchmark
---
-# 注意
+
+## 注意
+
此测试已经严重过时,不具备参考性。
-# 测试环境
+## 测试环境
+
- 系统:Linux core 3.16.0-7-amd64 #1 SMP Debian 3.16.59-1 (2018-10-03) x86_64 GNU/Linux
- 内存:15G
-- CPU:Intel(R) Xeon(R) CPU E3-1220 v5 @ 3.00GHz;4核
+- CPU:Intel(R) Xeon(R) CPU E3-1220 v5 @ 3.00GHz;4 核
- 网络:千兆网卡
- 测试端采用回环网络方式访问服务器
-# 测试工具
-ZLMeidaKit自带测试程序test_benchmark,其为单进程多线程模型
+## 测试工具
+
+ZLMeidaKit 自带测试程序 test_benchmark,其为单进程多线程模型
+
+## 测试服务器
+
+ZLMeidaKit 自带测试服务器 test_server,支持 RTSP/RTMP/HLS 服务器;多线程模型。
-# 测试服务器
-ZLMeidaKit自带测试服务器test_server,支持RTSP/RTMP/HLS服务器;多线程模型。
+## 测试媒体流
-# 测试媒体流
-使用test_server拉取的rtmp流`rtmp://live.hkstv.hk.lxdns.com/live/hks1`;然后通过test_server转发代理。
-该码流大概300~400Kbit/s左右。
+使用 test_server 拉取的 rtmp 流`rtmp://live.hkstv.hk.lxdns.com/live/hks1`;然后通过 test_server 转发代理。
+该码流大概 300~400Kbit/s 左右。
-# 测试结果
+## 测试结果
-说明:在cmake构建时,输入`cmake .. -DCMAKE_BUILD_TYPE=Release`以编译优化版本。
+说明:在 cmake 构建时,输入`cmake .. -DCMAKE_BUILD_TYPE=Release`以编译优化版本。
-| 播放器个数(rtmp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
-| --- | --- | --- | --- | --- |
-| 1000 | 20% | 702M/13M | 40 MByte/s | 无 |
-| 2000 | 39% | 702M/18M | 80 MByte/s | 无 |
-| 5000 | 92% | 702M/32M | 200 MByte/s | 无 |
-| 10000 | 170% | 702M/59M | 400 MByte/s | 无 |
+| 播放器个数(rtmp) | CPU(最大 400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
+| ---------------- | -------------- | -------------- | ----------- | ---- |
+| 1000 | 20% | 702M/13M | 40 MByte/s | 无 |
+| 2000 | 39% | 702M/18M | 80 MByte/s | 无 |
+| 5000 | 92% | 702M/32M | 200 MByte/s | 无 |
+| 10000 | 170% | 702M/59M | 400 MByte/s | 无 |
-| 播放器个数(rtsp/tcp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
-| --- | --- | --- | --- | --- |
-| 1000 | 18% | 702M/13M | 42 MByte/s| 无 |
-| 2000 | 35% | 702M/19M | 82 MByte/s | 无 |
-| 5000 | 80% | 702M/35M | 198 MByte/s | 无 |
-| 10000 | 130% | 702M/62M | 405 MByte/s | 无 |
+| 播放器个数(rtsp/tcp) | CPU(最大 400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
+| -------------------- | -------------- | -------------- | ----------- | ---- |
+| 1000 | 18% | 702M/13M | 42 MByte/s | 无 |
+| 2000 | 35% | 702M/19M | 82 MByte/s | 无 |
+| 5000 | 80% | 702M/35M | 198 MByte/s | 无 |
+| 10000 | 130% | 702M/62M | 405 MByte/s | 无 |
-# srs性能对比
-| 播放器个数(rtmp) | CPU(最大400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
-| --- | --- | --- | --- | --- |
-| 1000 | 10% | 310M/53M | 41.17 MByte/s | 无 |
-| 2000 | 18% | 604M/117M | 83.86 MByte/s | 无 |
+## srs 性能对比
+| 播放器个数(rtmp) | CPU(最大 400%) | 内存(VIRT/RES) | 带宽(平均) | 丢包 |
+| ---------------- | -------------- | -------------- | ------------- | ---- |
+| 1000 | 10% | 310M/53M | 41.17 MByte/s | 无 |
+| 2000 | 18% | 604M/117M | 83.86 MByte/s | 无 |
diff --git a/src/zh/reference/test/delay_test.md b/src/zh/reference/test/delay_test.md
index 4786057..a5ed852 100644
--- a/src/zh/reference/test/delay_test.md
+++ b/src/zh/reference/test/delay_test.md
@@ -3,60 +3,69 @@ title: 延时测试
---
## 注意
-此测试时间比较早,部分内容已失效;其中`ultraLowDelay`配置项已经删除;合并写延时改成0时(默认为0)即为最低延时模式;
-大家测试延时时,可以使用webrtc播放来测试。
+
+此测试时间比较早,部分内容已失效;其中`ultraLowDelay`配置项已经删除;合并写延时改成 0 时(默认为 0)即为最低延时模式;
+大家测试延时时,可以使用 webrtc 播放来测试。
## 网络环境
- - `localhost`
+
+- `localhost`
## 操作系统
- - `macOS`
-
+
+- `macOS`
+
## 服务器
- - `MediaServer`,启动参数 `-t 1` ,单线程启动
- - 配置文件打开`ultraLowDelay`模式
+
+- `MediaServer`,启动参数 `-t 1` ,单线程启动
+- 配置文件打开`ultraLowDelay`模式
## 推流器
- - `obs` rtmp推流到localhost
- - `速率控制`:`CBR`
- - `比特率`: 2500
- - `自定义缓存大小`: 100
- - `关键帧将`:2秒
- - `CPU使用预设`: `ultrafast`
- - `profile`: `baseline`
- - `Tune`: `zerolatency`
- - `分辨率`: 1280x720
- - `fps`: 30
-![image](https://user-images.githubusercontent.com/11495632/64311220-daf53f00-cfd5-11e9-8d1f-c39d95c335c4.png)
+
+- `obs` rtmp 推流到 localhost
+- `速率控制`:`CBR`
+- `比特率`: 2500
+- `自定义缓存大小`: 100
+- `关键帧将`:2 秒
+- `CPU使用预设`: `ultrafast`
+- `profile`: `baseline`
+- `Tune`: `zerolatency`
+- `分辨率`: 1280x720
+- `fps`: 30
+ ![image](https://user-images.githubusercontent.com/11495632/64311220-daf53f00-cfd5-11e9-8d1f-c39d95c335c4.png)
## 播放器
- - 内置test_player
- - localhost播放rtsp(udp、tcp模式都测试)或rtmp
+
+- 内置 test_player
+- localhost 播放 rtsp(udp、tcp 模式都测试)或 rtmp
## 测试方法
- - 打开浏览器,打开在线秒表网页 https://miaobiao.51240.com/
- - 设置OBS,截取浏览器秒表部分图像,开始推流给MediaServer
- - 打开test_player,播放对应的rtsp或rtmp url
- - 使用截图工具,定格画面,并对比网页与test_player播放器画面在线秒表时间差
+
+- 打开浏览器,打开在线秒表网页 https://miaobiao.51240.com/
+- 设置 OBS,截取浏览器秒表部分图像,开始推流给 MediaServer
+- 打开 test_player,播放对应的 rtsp 或 rtmp url
+- 使用截图工具,定格画面,并对比网页与 test_player 播放器画面在线秒表时间差
## 测试结果
- - 播放rtmp,延时200ms ~ 400ms
-![image](https://user-images.githubusercontent.com/11495632/64311009-0af01280-cfd5-11e9-9117-2f520db0b70f.png)
-![image](https://user-images.githubusercontent.com/11495632/64311040-2b1fd180-cfd5-11e9-8526-675d5d40d746.png)
- - 播放rtsp(tcp模式),延时200ms ~ 400ms
- ![image](https://user-images.githubusercontent.com/11495632/64311126-76d27b00-cfd5-11e9-89e4-59e9cb15b8bc.png)
- ![image](https://user-images.githubusercontent.com/11495632/64311161-9b2e5780-cfd5-11e9-96dd-5ab7eecc83ca.png)
+- 播放 rtmp,延时 200ms ~ 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311009-0af01280-cfd5-11e9-9117-2f520db0b70f.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311040-2b1fd180-cfd5-11e9-8526-675d5d40d746.png)
- - 播放rtsp(udp模式),延时200ms ~ 400ms
-![image](https://user-images.githubusercontent.com/11495632/64311179-b600cc00-cfd5-11e9-953f-07e73c377df1.png)
-![image](https://user-images.githubusercontent.com/11495632/64311187-c022ca80-cfd5-11e9-89b4-a015d614706e.png)
+- 播放 rtsp(tcp 模式),延时 200ms ~ 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311126-76d27b00-cfd5-11e9-89e4-59e9cb15b8bc.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311161-9b2e5780-cfd5-11e9-96dd-5ab7eecc83ca.png)
+
+- 播放 rtsp(udp 模式),延时 200ms ~ 400ms
+ ![image](https://user-images.githubusercontent.com/11495632/64311179-b600cc00-cfd5-11e9-953f-07e73c377df1.png)
+ ![image](https://user-images.githubusercontent.com/11495632/64311187-c022ca80-cfd5-11e9-89b4-a015d614706e.png)
## 测试结论
+
- 在单线程下,播放器和推流器在同一个线程,没有跨线程切换问题,延时稍微稳定并低点
-- 开启TCP_NODELAY关闭MSG_MORE在本轮测试中对优化延时效果不大
-- 多次截图平均下来有300ms左右的延时,最低200ms左右,最高有400+ms
-- 17年我自己写推流器(很遗憾没保存下exe文件)的情况下,最低延时能达到120ms左右,目前根本达不到,怀疑obs推流延时还是较高
-- 推流时建议关闭音频再测试,像AAC这种编码格式,编码延时能达到100ms以上
-- 本次测试都是再macOS下测试的,理想情况下,服务器是linux,推流器windows,播放器渲染自己做的话延时可能还能更低
-- 感兴趣的朋友们可以在windows下测试下,17年我是在局域网中测试的,推流器、服务器、播放器都不是同一台主机,延时尚且低至120ms,如果localhost应该能更低。
+- 开启 TCP_NODELAY 关闭 MSG_MORE 在本轮测试中对优化延时效果不大
+- 多次截图平均下来有 300ms 左右的延时,最低 200ms 左右,最高有 400+ms
+- 17 年我自己写推流器(很遗憾没保存下 exe 文件)的情况下,最低延时能达到 120ms 左右,目前根本达不到,怀疑 obs 推流延时还是较高
+- 推流时建议关闭音频再测试,像 AAC 这种编码格式,编码延时能达到 100ms 以上
+- 本次测试都是再 macOS 下测试的,理想情况下,服务器是 linux,推流器 windows,播放器渲染自己做的话延时可能还能更低
+- 感兴趣的朋友们可以在 windows 下测试下,17 年我是在局域网中测试的,推流器、服务器、播放器都不是同一台主机,延时尚且低至 120ms,如果 localhost 应该能更低。
diff --git a/src/zh/reference/test/how_to_test_delay.md b/src/zh/reference/test/how_to_test_delay.md
index 6be3add..e6227a1 100644
--- a/src/zh/reference/test/how_to_test_delay.md
+++ b/src/zh/reference/test/how_to_test_delay.md
@@ -1,10 +1,13 @@
---
title: 怎么测试ZLMediaKit的延时?
---
+
## 引言
-有些小伙伴们经常在群里面问我,为什么用ZLMediaKit拉流代理、推流转发的流播放延时好几秒,长的时候10多秒?为什么HLS延时更高,动辄延时半分钟?本文的目的在于澄清大家对延时的误解。
+
+有些小伙伴们经常在群里面问我,为什么用 ZLMediaKit 拉流代理、推流转发的流播放延时好几秒,长的时候 10 多秒?为什么 HLS 延时更高,动辄延时半分钟?本文的目的在于澄清大家对延时的误解。
## 什么是延时
+
很多小伙伴们并不能明白什么叫延时,认为随便一个播放器播放出来的画面跟原始流画面时间差就是延时,其实这是对延时最大的误解。
延时不是表象,很多人在测试延时时很不专业,对延时测试的专业性认识不足,在此我特别提醒,不是随随便便的播放器都有资格做延时测试的!
@@ -12,61 +15,53 @@ title: 怎么测试ZLMediaKit的延时?
- **采集延时**
-在采集摄像头或显卡画面时,由于fps的限制和cpu性能、内存拷贝速度等客观限制,采集画面成YUV/RGB等数据时会有一定的延时,一般延时为毫秒级别。由于一般编码器对输入数据格式存在限制,譬如要求统一输入YUV420P,这样在做RGB->YUV420P转换时,也会有转换计算延时(这个可以通过libyuv库来降低)。总而言之,采集延时大概为毫秒级别,如果fps为30,那么一般采集延时会有30毫秒以上的延时,在内存拷贝和颜色转换时,又可能增加若干毫秒的延时。
-
+ 在采集摄像头或显卡画面时,由于 fps 的限制和 cpu 性能、内存拷贝速度等客观限制,采集画面成 YUV/RGB 等数据时会有一定的延时,一般延时为毫秒级别。由于一般编码器对输入数据格式存在限制,譬如要求统一输入 YUV420P,这样在做 RGB->YUV420P 转换时,也会有转换计算延时(这个可以通过 libyuv 库来降低)。总而言之,采集延时大概为毫秒级别,如果 fps 为 30,那么一般采集延时会有 30 毫秒以上的延时,在内存拷贝和颜色转换时,又可能增加若干毫秒的延时。
- **编码延时**
-在把原始画面输入到编码器时,并不会立即输出编码后的数据,特别是在开启B帧时,由于需要参考后面的P帧,那么延时会更大,所以延时敏感的情况下一般不开启B帧,这种情况下编码延时应该是毫秒级别,不是很大。
-
+ 在把原始画面输入到编码器时,并不会立即输出编码后的数据,特别是在开启 B 帧时,由于需要参考后面的 P 帧,那么延时会更大,所以延时敏感的情况下一般不开启 B 帧,这种情况下编码延时应该是毫秒级别,不是很大。
- **网络上行传输延时**
-编码后的数据,要经过一定的协议打包才能写入socket,然后传输给推流服务器或拉流代理服务器,协议打包会有一定的内存拷贝和计算量,那么会增加延时,不过这个延时很小,基本忽略不计。数据在上传到服务器时,这个延时可大可小,取决于网络质量。
-
+ 编码后的数据,要经过一定的协议打包才能写入 socket,然后传输给推流服务器或拉流代理服务器,协议打包会有一定的内存拷贝和计算量,那么会增加延时,不过这个延时很小,基本忽略不计。数据在上传到服务器时,这个延时可大可小,取决于网络质量。
- **服务器转协议延时**
-服务器在收到数据后,要读socket缓存、协议解析、解复用、重新打包等操作,不过总体而言,这个延时比较小,基本没什么影响。有时,服务器为了提高性能,会采取合并写的机制,也就是收到一定量的数据后才会一并转发,这个延时一般为几百毫秒,ZLMediaKit默认300毫秒左右,不过ZLMediaKit默认关闭合并写,也就是这个延时也很小。
+ 服务器在收到数据后,要读 socket 缓存、协议解析、解复用、重新打包等操作,不过总体而言,这个延时比较小,基本没什么影响。有时,服务器为了提高性能,会采取合并写的机制,也就是收到一定量的数据后才会一并转发,这个延时一般为几百毫秒,ZLMediaKit 默认 300 毫秒左右,不过 ZLMediaKit 默认关闭合并写,也就是这个延时也很小。
- **网络下行延时**
-流媒体在把视频数据转发给播放器时,会存在网络发送,这个延时大小取决于网络质量,ZLMediaKit在关闭低延时模式时,还会增加MSG_MORE和关闭TCP_NODELAY导致的延时,不过ZLMediaKit默认开启低延时模式。
-
+ 流媒体在把视频数据转发给播放器时,会存在网络发送,这个延时大小取决于网络质量,ZLMediaKit 在关闭低延时模式时,还会增加 MSG_MORE 和关闭 TCP_NODELAY 导致的延时,不过 ZLMediaKit 默认开启低延时模式。
- **播放器延时**
-播放器延时主要有网络接收延时、协议解析解复用延时、解码延时、缓存延时、渲染延时组成,这些延时中**缓存延时**最大,因为一般的播放器为了保证在网络抖动情况下视频播放的流畅性,会以增加延时为代价,增加播放缓存,这样在网络变差时,不至于播放缓冲卡顿。而且为了音视频同步,也必须确保一定的缓存量。这种延时一般都是秒级别,一般5秒左右。
-
-- **播放器GOP缓存延时**
+ 播放器延时主要有网络接收延时、协议解析解复用延时、解码延时、缓存延时、渲染延时组成,这些延时中**缓存延时**最大,因为一般的播放器为了保证在网络抖动情况下视频播放的流畅性,会以增加延时为代价,增加播放缓存,这样在网络变差时,不至于播放缓冲卡顿。而且为了音视频同步,也必须确保一定的缓存量。这种延时一般都是秒级别,一般 5 秒左右。
-流媒体服务器为了能让播放器立即出画面,往往会缓存最近的一个I帧,这个I帧往后的所有音视频数据被称作为GOP缓存。如果不缓存GOP,那么播放器要等下一个I帧才能解码成功或不花屏,显然为了提高播放体验,这个GOP缓存是不能去掉的。而一般GOP短则1~3秒,长则10几秒,这个跟采集端编码器设置有关,服务器改变不了。但是由于一般的播放器收到缓存后,并不会丢弃过多的画面来确保低延时。况且播放器还希望有一定的缓存来确保播放的流畅性,所以这个GOP缓存将会增大播放器的延时。
+- **播放器 GOP 缓存延时**
+ 流媒体服务器为了能让播放器立即出画面,往往会缓存最近的一个 I 帧,这个 I 帧往后的所有音视频数据被称作为 GOP 缓存。如果不缓存 GOP,那么播放器要等下一个 I 帧才能解码成功或不花屏,显然为了提高播放体验,这个 GOP 缓存是不能去掉的。而一般 GOP 短则 1~3 秒,长则 10 几秒,这个跟采集端编码器设置有关,服务器改变不了。但是由于一般的播放器收到缓存后,并不会丢弃过多的画面来确保低延时。况且播放器还希望有一定的缓存来确保播放的流畅性,所以这个 GOP 缓存将会增大播放器的延时。
- **综合延时**
-以上所有的延时累加,就是你观看到的直观延时,那么你看到的延时很高,能怪是服务器的问题吗?在理想的网络状况下,你观看到的直观延时,其实约等于播放器的播放缓存延时,这个锅得由播放器来背。
-
+ 以上所有的延时累加,就是你观看到的直观延时,那么你看到的延时很高,能怪是服务器的问题吗?在理想的网络状况下,你观看到的直观延时,其实约等于播放器的播放缓存延时,这个锅得由播放器来背。
## 怎么测试延时
-用vlc等通用播放器测试延时是很不专业的,这些播放器延时最少是秒级别的,为了播放流畅度和音视频同步,这些播放器是不可能给你真实的延时数据。
-在此,我强烈推荐大家自己写个无缓存的播放器测试延时,但是这显然超过了大部人的能力,所以ZLMediaKit提供了一个简单的播放器测试延时:
+用 vlc 等通用播放器测试延时是很不专业的,这些播放器延时最少是秒级别的,为了播放流畅度和音视频同步,这些播放器是不可能给你真实的延时数据。
+
+在此,我强烈推荐大家自己写个无缓存的播放器测试延时,但是这显然超过了大部人的能力,所以 ZLMediaKit 提供了一个简单的播放器测试延时:
[test_player](https://github.com/ZLMediaKit/ZLMediaKit/blob/master/player/test_player.cpp)
-什么? 你告诉我你不会编译ZLMediaKit? 那好,退而求其次,我推荐你使用webrtc播放来测试zlm延时;也可以用ffplay测试:
+什么? 你告诉我你不会编译 ZLMediaKit? 那好,退而求其次,我推荐你使用 webrtc 播放来测试 zlm 延时;也可以用 ffplay 测试:
```bash
ffplay -i rtmp://xxxxxxx -fflags nobuffer
```
-如果你不知道ffplay怎么安装,你可以从[这里](http://ffmpeg.org/download.html)下载编译好的.
-
-
+如果你不知道 ffplay 怎么安装,你可以从[这里](http://ffmpeg.org/download.html)下载编译好的.
## 关于延时的更多信息
+
[直播延时的本质](../documents/the_nature_of_live_broadcast_delay.md)
[延时相关测试](./delay_test.md)
-
-
diff --git a/src/zh/reference/test/online_test.md b/src/zh/reference/test/online_test.md
index 1ba647a..e3b2ebd 100644
--- a/src/zh/reference/test/online_test.md
+++ b/src/zh/reference/test/online_test.md
@@ -1,14 +1,16 @@
---
title: 在线测试
---
+
## 测试地址
-- http/hls/http-flv/ws-flv地址: http://zlmediakit.com:8888/
-- https地址: https://zlmediakit.com/
-- rtsp地址: zlmediakit.com:554
-- rtmp地址: zlmediakit.com:1935
-- GB28181 UDP/TCP地址: zlmediakit.com:10000
+
+- http/hls/http-flv/ws-flv 地址: http://zlmediakit.com:8888/
+- https 地址: https://zlmediakit.com/
+- rtsp 地址: zlmediakit.com:554
+- rtmp 地址: zlmediakit.com:1935
+- GB28181 UDP/TCP 地址: zlmediakit.com:10000
## 开始测试
+
[推流测试](../../guide/media_server/push_test.md)
[播放测试](../../guide/media_server/play_url_rules.md)
-
diff --git a/src/zh/reference/test/performance_testing.md b/src/zh/reference/test/performance_testing.md
index 4851f4a..2c1babb 100644
--- a/src/zh/reference/test/performance_testing.md
+++ b/src/zh/reference/test/performance_testing.md
@@ -2,11 +2,11 @@
title: 性能测试
---
-# 一、最新性能测试:
+## 一、最新性能测试
-## 1.1、测试环境
+### 1.1、测试环境
-- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz 4核8线程
+- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz 4 核 8 线程
- 操作系统:CentOS release 6.3 (Final)
- 内存:16GB
- 网卡:127.0.0.1
@@ -14,37 +14,36 @@ title: 性能测试
- 编译器:gcc (GCC) 8.2.0
- 编译类型:Release
+### 1.2、测试数据
-## 1.2、测试数据
+> 推流性能测试内存占用部分存在不准确问题(原因是当时测试时有个多 gop 缓存 bug)
-> 推流性能测试内存占用部分存在不准确问题(原因是当时测试时有个多gop缓存bug)
+| 客户端类型 | 流个数 | cpu | 内存 | 网络 io | 4 物理核 cpu 理论性能 |
+| :--------: | :----: | :--: | :--: | :------: | :-------------------: |
+| rtsp 播放 | 20K | 160% | 203M | 5Gb/s | 约 100K |
+| rtsp 播放 | 32.2K | 235% | 220M | 7.78Gb/s | 约 100K |
+| rtsp 推流 | 10K | 264% | 760M | 2.39Gb/s | 约 30K |
+| | | | | | |
+| rtmp 播放 | 10K | 148% | 81M | 2.33Gb/s | 约 50K |
+| rtmp 播放 | 30K | 450% | 246M | 7Gb/s | 约 50K |
+| rtmp 推流 | 10K | 224% | 1.6G | 2.16Gb/s | 约 30K |
-| 客户端类型 | 流个数 | cpu | 内存 | 网络io | 4物理核cpu理论性能 |
-| :--------: | :----: | :--: | :--: | :------: | :------------: |
-| rtsp播放 | 20K | 160% | 203M | 5Gb/s | 约100K |
-| rtsp播放 | 32.2K | 235% | 220M | 7.78Gb/s | 约100K |
-| rtsp推流 | 10K | 264% | 760M | 2.39Gb/s | 约30K |
-| | | | | | |
-| rtmp播放 | 10K | 148% | 81M | 2.33Gb/s | 约50K |
-| rtmp播放 | 30K | 450% | 246M | 7Gb/s | 约50K |
-| rtmp推流 | 10K | 224% | 1.6G | 2.16Gb/s | 约30K |
+### 1.3、测试详细数据
-## 1.3、测试详细数据
-- [rtmp拉流](./rtmp_pull_stream_performance_test.md)
-- [rtmp推流](./rtmp_push_stream_performance_test.md)
-- [rtsp拉流](./rtsp_pull_stream_performance_test.md)
-- [rtsp推流](./rtsp_push_stream_performance_test.md)
+- [rtmp 拉流](./rtmp_pull_stream_performance_test.md)
+- [rtmp 推流](./rtmp_push_stream_performance_test.md)
+- [rtsp 拉流](./rtsp_pull_stream_performance_test.md)
+- [rtsp 推流](./rtsp_push_stream_performance_test.md)
+## 二、较早的性能测试记录
-# 二、较早的性能测试记录
-- [rtmp拉流性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/406)
-- [GB28181性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
-- [rtsp音频拉流性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/1271)
+- [rtmp 拉流性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/406)
+- [GB28181 性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/961)
+- [rtsp 音频拉流性能测试](https://github.com/ZLMediaKit/ZLMediaKit/issues/1271)
- [过时的性能测试记录](./benchmark.md)
-# 三、性能测试与优化
-- [rtsp性能优化与测试](../development_log/rtsp_performance_optimization.md)
-- [hls性能优化与测试](../development_log/hls_high_performance_journey.md)
-- [rtmp性能优化](https://github.com/ZLMediaKit/ZLMediaKit/issues/540)
-
+## 三、性能测试与优化
+- [rtsp 性能优化与测试](../development_log/rtsp_performance_optimization.md)
+- [hls 性能优化与测试](../development_log/hls_high_performance_journey.md)
+- [rtmp 性能优化](https://github.com/ZLMediaKit/ZLMediaKit/issues/540)
diff --git a/src/zh/reference/test/rtmp_pull_stream_performance_test.md b/src/zh/reference/test/rtmp_pull_stream_performance_test.md
index d218a71..2a0c9d9 100644
--- a/src/zh/reference/test/rtmp_pull_stream_performance_test.md
+++ b/src/zh/reference/test/rtmp_pull_stream_performance_test.md
@@ -1,7 +1,9 @@
---
-title: rtmp拉流性能测试
+title: rtmp 拉流性能测试
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtmp拉流性能测试
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtmp拉流性能测试(1万路)
+## 二、rtmp 拉流性能测试(1 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,23 +73,22 @@ ulimit -n 102400
./test_bench_pull -c 10000 -i rtmp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169045558-bcf711b8-b27c-4372-a1d2-ccb0e1a33d65.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169045971-ebf7da67-00f1-4c63-8c17-3c27937a5016.png)
-- nload信息(平均2.34Gb/s):
+- nload 信息(平均 2.34Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169046147-39376f04-471b-4de2-a345-0e41982a612b.png)
-
-# 三、rtmp拉流性能测试(3万路)
+## 三、rtmp 拉流性能测试(3 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -91,20 +96,14 @@ ulimit -n 102400
./test_bench_pull -c 30000 -i rtmp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169049433-97174931-5f6b-45db-a320-0c4257b37fad.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169049184-951a7108-c3e6-451f-97c9-164abf439ed2.png)
-
-- nload信息(平均7.09Gb/s):
+- nload 信息(平均 7.09Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169049082-cf6c665f-b876-4e7d-91d6-391b10ec2b52.png)
-
-
-
-
diff --git a/src/zh/reference/test/rtmp_push_stream_performance_test.md b/src/zh/reference/test/rtmp_push_stream_performance_test.md
index 9b7a2a6..b2fe7e1 100644
--- a/src/zh/reference/test/rtmp_push_stream_performance_test.md
+++ b/src/zh/reference/test/rtmp_push_stream_performance_test.md
@@ -1,7 +1,9 @@
---
-title: rtmp推流性能测试
+title: rtmp 推流性能测试
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtmp推流性能测试
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtmp推流性能测试(1万路)
+## 二、rtmp 推流性能测试(1 万路)
- 推流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,24 +73,14 @@ ulimit -n 102400
./test_bench_push -i rtmp://127.0.0.1/live/test -c 10000 -o rtmp://127.0.0.1/live/push
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169197952-9a042459-a3fe-4b48-903b-4aa0095dfe77.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198018-1a823b57-4e9f-4331-950d-329178c40de8.png)
-
-- nload信息(平均2.16Gb/s):
+- nload 信息(平均 2.16Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169198085-5c4278f1-c4dc-421a-992c-aac94d090479.png)
-
-
-
-
-
-
-
-
diff --git a/src/zh/reference/test/rtsp_pull_stream_performance_test.md b/src/zh/reference/test/rtsp_pull_stream_performance_test.md
index 4f4d449..6f1b185 100644
--- a/src/zh/reference/test/rtsp_pull_stream_performance_test.md
+++ b/src/zh/reference/test/rtsp_pull_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtsp拉流性能测试
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtsp拉流性能测试
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtsp拉流性能测试(2万路)
+## 二、rtsp 拉流性能测试(2 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,25 +73,22 @@ ulimit -n 102400
./test_bench_pull -c 20000 -i rtsp://127.0.0.1/live/test
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169055524-10ec0ab2-23a2-4103-b2c4-0c5affb61b85.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169055647-1c3599a8-63e6-4d08-8179-69e74eed05e4.png)
-
-- nload信息(平均5Gb/s):
+- nload 信息(平均 5Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169055992-16e0c2a6-58db-4683-912a-6e7f94783350.png)
-
-
-# 三、rtsp拉流性能测试(4万路)
+## 三、rtsp 拉流性能测试(4 万路)
- 拉流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -93,27 +96,17 @@ ulimit -n 102400
./test_bench_pull -c 40000 -i rtsp://127.0.0.1/live/test
```
-- 发现由于随机端口不够,有些播放器掉线(只剩32244个):
-![图片](https://user-images.githubusercontent.com/11495632/169060039-9bfddd5c-62d3-4ddf-8c20-176e7ab4c8b0.png)
+- 发现由于随机端口不够,有些播放器掉线(只剩 32244 个):
+ ![图片](https://user-images.githubusercontent.com/11495632/169060039-9bfddd5c-62d3-4ddf-8c20-176e7ab4c8b0.png)
-
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169059095-d15b9645-e80e-40ba-a607-31896b90db0c.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169059190-f4bcae26-c037-49c5-a4c0-002f4d96847f.png)
-- nload信息(平均7.78Gb/s):
+- nload 信息(平均 7.78Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169059778-2c525923-75e5-4935-b489-817249941c6a.png)
-
-
-
-
-
-
-
-
diff --git a/src/zh/reference/test/rtsp_push_stream_performance_test.md b/src/zh/reference/test/rtsp_push_stream_performance_test.md
index 0a6a60e..0d5151a 100644
--- a/src/zh/reference/test/rtsp_push_stream_performance_test.md
+++ b/src/zh/reference/test/rtsp_push_stream_performance_test.md
@@ -1,7 +1,9 @@
---
title: rtsp推流性能测试
---
-# 一、测试环境
+
+## 一、测试环境
+
- 测试日期:2022/5/18
- 代码版本:git hash: c7d7999f
- cpu: Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
@@ -10,9 +12,10 @@ title: rtsp推流性能测试
- 网卡:127.0.0.1
- 测试码流: [200kbps.768x320.flv](https://raw.githubusercontent.com/ossrs/srs/develop/trunk/doc/source.200kbps.768x320.flv)
- 编译器:gcc (GCC) 8.2.0
-- zlmediakit编译类型:Release
-- malloc库:ptmalloc(未开启jemalloc)
-- config.ini配置文件修改(主要开启合并写、按需转协议):
+- zlmediakit 编译类型:Release
+- malloc 库:ptmalloc(未开启 jemalloc)
+- config.ini 配置文件修改(主要开启合并写、按需转协议):
+
```patch
diff --git a/conf/config.ini b/conf/config.ini
index c2d4613f..99ce5c84 100644
@@ -34,7 +37,7 @@ index c2d4613f..99ce5c84 100644
#该开关对rtsp/rtmp/rtp推流、rtsp/rtmp/hls拉流代理转协议时生效
#会直接影响rtsp/rtmp/hls/mp4/flv等协议的时间戳
@@ -72,15 +72,15 @@ enable_audio=1
- ###### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
+ ####### 如果某种协议你想获取最好的用户体验,请置0(第一个播放者可以秒开,且不花屏)
#hls协议是否按需生成,如果hls.segNum配置为0(意味着hls录制),那么hls将一直生成(不管此开关)
-hls_demand=0
@@ -52,14 +55,17 @@ index c2d4613f..99ce5c84 100644
-fmp4_demand=0
+fmp4_demand=1
```
+
- 推流命令:
+
```bash
ffmpeg -stream_loop -1 -re -i ~/Downloads/source.200kbps.768x320.flv -acodec copy -vcodec copy -f flv rtmp://ip:port/live/test
```
-# 二、rtsp推流性能测试(1万路)
+## 二、rtsp 推流性能测试(1 万路)
- 推流命令:
+
```bash
#加大文件描述符个数
ulimit -n 102400
@@ -67,28 +73,14 @@ ulimit -n 102400
./test_bench_push -i rtmp://127.0.0.1/live/test -c 10000 -o rtsp://127.0.0.1/live/push
```
-- top信息:
+- top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198621-85d3a0f3-ffc4-4e2d-bdb8-8e886130ff2e.png)
-
-- perf top信息:
+- perf top 信息:
![图片](https://user-images.githubusercontent.com/11495632/169198658-7ca9599c-16da-4dd9-8fb5-aa35d35cbe97.png)
-
-- nload信息(平均2.39Gb/s):
+- nload 信息(平均 2.39Gb/s):
![图片](https://user-images.githubusercontent.com/11495632/169198759-7baa33a2-30fe-409b-a0bf-e737be849ad1.png)
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/zh/tutorial/README.md b/src/zh/tutorial/README.md
index f1a1f0b..07d11d3 100644
--- a/src/zh/tutorial/README.md
+++ b/src/zh/tutorial/README.md
@@ -3,56 +3,51 @@ title: 快速开始
icon: lightbulb
description: 本教程将指导您完成编译和运行ZLMediaKit.
---
-## 1、获取代码
-
-**请不要使用github 下载zip包的方式下载源码**,务必使用git克隆ZLMediaKit的代码,因为ZLMediaKit依赖于第三方代码,zip包不会下载第三方依赖源码,你可以这样操作:
- ```bash
- #国内用户推荐从同步镜像网站gitee下载
- git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
- cd ZLMediaKit
- #千万不要忘记执行这句命令
- git submodule update --init
- ```
+## 1、获取代码
+**请不要使用 github 下载 zip 包的方式下载源码**,务必使用 git 克隆 ZLMediaKit 的代码,因为 ZLMediaKit 依赖于第三方代码,zip 包不会下载第三方依赖源码,你可以这样操作:
+```bash
+#国内用户推荐从同步镜像网站gitee下载
+git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+cd ZLMediaKit
+#千万不要忘记执行这句命令
+git submodule update --init
+```
## 2、强烈推荐
-如果你是位新手,强烈建议使用ubuntu16或更新版本编译ZLMediaKit,macOS是次选推荐平台,最不推荐的是centos6.*或windows平台。
-
-zlmediakit已上架vcpkg,便捷安装请参考[vcpkg安装zlmediakit](../guide/install/install_zlmediakit_using_vcpkg.md)
-
+如果你是位新手,强烈建议使用 ubuntu16 或更新版本编译 ZLMediaKit,macOS 是次选推荐平台,最不推荐的是 centos6.\*或 windows 平台。
+zlmediakit 已上架 vcpkg,便捷安装请参考[vcpkg 安装 zlmediakit](../guide/install/install_zlmediakit_using_vcpkg.md)
## 3、编译器
### 3.1、编译器版本要求
-ZLMediaKit采用了C++11的语法和库,要求编译器支持完整的C++11标准,亦即:
-
-- linux上要求gcc 版本 >= 4.8(4.7应该也能支持)
-- macOS上clang >= ???(我也不知道,估计大部分不会遇到这个问题)
-- windows 上visual stuido >= 2015(vs2013某些版本也能编译通过,如果怕麻烦建议直接vs2017)
-
+ZLMediaKit 采用了 C++11 的语法和库,要求编译器支持完整的 C++11 标准,亦即:
+- linux 上要求 gcc 版本 >= 4.8(4.7 应该也能支持)
+- macOS 上 clang >= ???(我也不知道,估计大部分不会遇到这个问题)
+- windows 上 visual stuido >= 2015(vs2013 某些版本也能编译通过,如果怕麻烦建议直接 vs2017)
### 3.2、安装编译器
-- 如果你是debian系操作系统(包括ubuntu系用户),一般自带的gcc版本够新,你可以这样安装gcc编译器:
+- 如果你是 debian 系操作系统(包括 ubuntu 系用户),一般自带的 gcc 版本够新,你可以这样安装 gcc 编译器:
```bash
sudo apt-get install build-essential
```
-- 如果你是centos7或以上用户,你可以这样安装gcc编译器:
+- 如果你是 centos7 或以上用户,你可以这样安装 gcc 编译器:
```cpp
sudo yum -y install gcc
sudo yum -y install gcc-c++
```
-- 如果你是centos6.*用户,你可以这样安装gcc编译器:
+- 如果你是 centos6.\*用户,你可以这样安装 gcc 编译器:
```bash
sudo yum install centos-release-scl -y
@@ -61,29 +56,27 @@ ZLMediaKit采用了C++11的语法和库,要求编译器支持完整的C++11标
scl enable devtoolset-4 bash
```
-- 如果你是macOS用户,你直接安装xcode即可。
-
-- 如果你是windows用户,推荐安装vs2017或以上。
-
+- 如果你是 macOS 用户,你直接安装 xcode 即可。
+- 如果你是 windows 用户,推荐安装 vs2017 或以上。
## 4、cmake
-ZLMediaKit采用cmake来构建项目,通过cmake才能生成Makefile(或Xcode/VS工程),所以必须先安装cmake才能完成后续步骤。
+ZLMediaKit 采用 cmake 来构建项目,通过 cmake 才能生成 Makefile(或 Xcode/VS 工程),所以必须先安装 cmake 才能完成后续步骤。
-- 如果你是debian系操作系统(包括ubuntu系用户),一般自带的cmake版本够新,你可以这样安装cmake
+- 如果你是 debian 系操作系统(包括 ubuntu 系用户),一般自带的 cmake 版本够新,你可以这样安装 cmake
```bash
sudo apt-get install cmake
```
-- 如果你是centos7或以上用户,你也许可以这样安装cmake:
+- 如果你是 centos7 或以上用户,你也许可以这样安装 cmake:
```cpp
sudo yum -y install cmake
```
-- 如果你是centos6.*用户,那么你需要下载新版本的cmake源码然后编译安装cmake
+- 如果你是 centos6.\*用户,那么你需要下载新版本的 cmake 源码然后编译安装 cmake
```bash
wget https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3.tar.gz
@@ -94,56 +87,45 @@ ZLMediaKit采用cmake来构建项目,通过cmake才能生成Makefile(或Xcode/
sudo make install
```
-- 如果你是macOS用户,你可以这样安装cmake:
+- 如果你是 macOS 用户,你可以这样安装 cmake:
```bash
brew install cmake
```
-
-- 如果你是windows用户,并且vs版本为2017及以上,你不用单独安装cmake,否则你需要安装cmake-gui:
+- 如果你是 windows 用户,并且 vs 版本为 2017 及以上,你不用单独安装 cmake,否则你需要安装 cmake-gui:
```bash
#安装win64版本cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win64-x64.zip
-
+
#安装win32版本cmake
https://github.com/Kitware/CMake/releases/download/v3.17.0-rc3/cmake-3.17.0-rc3-win32-x86.zip
```
-
-
## 5、依赖库
### 5.1、依赖库列表
-ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构建ZLMediaKit时,cmake能查找系统路径中的这些库,并根据安装情况选择是否开启相关特性,你可以选择安装这些依赖并启用相关特性:
+ZLMediaKit 可选依赖一些第三方库,这些库都不是必选的;在构建 ZLMediaKit 时,cmake 能查找系统路径中的这些库,并根据安装情况选择是否开启相关特性,你可以选择安装这些依赖并启用相关特性:
- openssl
- - flash player在播放rtmp时,采用的是复杂握手模式,如果不安装该库,flash player将播放不了zlmediakit 提供的rtmp url.
-
- - 同时ZLMediaKit的https/rtsps/webrtc相关功能需要使用openssl才能开启。
-
-
+ - flash player 在播放 rtmp 时,采用的是复杂握手模式,如果不安装该库,flash player 将播放不了 zlmediakit 提供的 rtmp url.
+ - 同时 ZLMediaKit 的 https/rtsps/webrtc 相关功能需要使用 openssl 才能开启。
- ffmpeg
- zlmediakit可以通过fork ffmpeg进程的方式实现多种协议的拉流,编译时不需要安装FFmpeg。
-
-
+ zlmediakit 可以通过 fork ffmpeg 进程的方式实现多种协议的拉流,编译时不需要安装 FFmpeg。
- sdl、avcodec、avutil
- 这3个库供ZLMediaKit的test_player测试程序使用,你通常不需要安装这3个库。
-
-
-
+ 这 3 个库供 ZLMediaKit 的 test_player 测试程序使用,你通常不需要安装这 3 个库。
### 5.2、安装依赖库
-- Debian系(包括ubuntu)系统下安装依赖的方法:
+- Debian 系(包括 ubuntu)系统下安装依赖的方法:
```sh
#除了openssl,其他其实都可以不安装
@@ -153,24 +135,24 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
sudo apt-get install libavutil-dev
sudo apt-get install ffmpeg
```
-- centos6.*的用户可以参考该[文章](https://blog.51cto.com/mengix/2452395)
-- macOS/centos下安装依赖库:
+- centos6.\*的用户可以参考该[文章](https://blog.51cto.com/mengix/2452395)
- 基本安装方式跟Debian系安装差不多,安装命令分别改成brew / yum即可。但是有些库名字与Debian系不太一样,请自行查找相关资料。
+- macOS/centos 下安装依赖库:
-- windows下安装依赖库
+ 基本安装方式跟 Debian 系安装差不多,安装命令分别改成 brew / yum 即可。但是有些库名字与 Debian 系不太一样,请自行查找相关资料。
- - 安装openssl
+- windows 下安装依赖库
- 请从[网站](http://slproweb.com/products/Win32OpenSSL.html)中下载。
+ - 安装 openssl
+ 请从[网站](http://slproweb.com/products/Win32OpenSSL.html)中下载。
## 6、构建和编译项目
-由于开启webrtc相关功能比较复杂,默认是不开启编译的,如果你对zlmediakit的webrtc功能比较感兴趣,可以参考[这里](../guide/protocol/webrtc/webrtc_compilation_and_use.md)
+由于开启 webrtc 相关功能比较复杂,默认是不开启编译的,如果你对 zlmediakit 的 webrtc 功能比较感兴趣,可以参考[这里](../guide/protocol/webrtc/webrtc_compilation_and_use.md)
-- 在linux或macOS系统下,你应该这样操作:
+- 在 linux 或 macOS 系统下,你应该这样操作:
```bash
cd ZLMediaKit
@@ -181,11 +163,9 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
make -j4
```
+- 在 windows 系统下
-
-- 在windows系统下
-
- - 如果你是vs2017或以上,可以在vs菜单栏中直接打开项目文件夹:
+ - 如果你是 vs2017 或以上,可以在 vs 菜单栏中直接打开项目文件夹:
```bash
[文件] -> [打开] -> [文件夹] -> [选择ZLMediaKit代码根目录并打开]
@@ -193,7 +173,7 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
![image](/images/vs_code_zh.png)
- - 如果你是vs2017以下版本,你需要使用cmake-gui生成vs工程然后编译:
+ - 如果你是 vs2017 以下版本,你需要使用 cmake-gui 生成 vs 工程然后编译:
```sh
1 进入ZLMediaKit目录执行 git submodule update --init 以下载ZLToolKit的代码
@@ -202,14 +182,12 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
4 选择编译Release 版本.
5 找到目标文件并运行测试用例.
```
- - 同时,Windows编译也可以参考[这里](../guide/install/compilation_instructions_for_windows_version.md)
-
-- 如果你要编译Android版本,你可以自己在Android Studio中打开Android目录。
+ - 同时,Windows 编译也可以参考[这里](../guide/install/compilation_instructions_for_windows_version.md)
+- 如果你要编译 Android 版本,你可以自己在 Android Studio 中打开 Android 目录。
-
-- 如果你要编译ios版本,可以生成xcode工程然后编译c api的静态库;另外,你可以参考此[文档](https://www.jianshu.com/p/44c21296add5)
+- 如果你要编译 ios 版本,可以生成 xcode 工程然后编译 c api 的静态库;另外,你可以参考此[文档](https://www.jianshu.com/p/44c21296add5)
```sh
cd ZLMediaKit
@@ -219,20 +197,16 @@ ZLMediaKit可选依赖一些第三方库,这些库都不是必选的;在构
cmake .. -G Xcode -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.toolchain.cmake -DPLATFORM=OS64COMBINED
```
-
-
## 7、运行
-ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径在release目录下,这些目标文件主要分为:
+ZLMediaKit 工程主要生成 3 种二进制目标文件,他们的生成的路径在 release 目录下,这些目标文件主要分为:
-- MediaServer进程
+- MediaServer 进程
- 这是ZLMediaKit作为服务器的主进程,该进程可以在免去开发的情况下直接作为测试流媒体服务器使用,如果你需要更复杂的业务逻辑,可以通过[Web HOOK](../guide/media_server/web_hook_api.
+ 这是 ZLMediaKit 作为服务器的主进程,该进程可以在免去开发的情况下直接作为测试流媒体服务器使用,如果你需要更复杂的业务逻辑,可以通过[Web HOOK](../guide/media_server/web_hook_api.
md)和[RESTful API](../guide/media_server/restful_api.md)实现,同时你可以通过[配置文件](../guide/media_server/config_file.md)控制其参数。
-
-
- - 在linux下启动:
+ - 在 linux 下启动:
```sh
cd ZLMediaKit/release/linux/Debug
@@ -242,15 +216,11 @@ ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径
./MediaServer -d &
```
-
-
- - 在macos下启动:
+ - 在 macos 下启动:
- 目标文件目录在ZLMediaKit/mac/Debug,其他操作完全一致。
+ 目标文件目录在 ZLMediaKit/mac/Debug,其他操作完全一致。
-
-
- - 在window下启动:
+ - 在 window 下启动:
```sh
1 进入ZLMediaKit/release/windows/Debug目录
@@ -258,42 +228,35 @@ ZLMediaKit工程主要生成3种二进制目标文件,他们的生成的路径
3 你也可以在cmd或powershell中启动,通过MediaServer -h了解启动参数
```
-
-
-- c api 的SDK
+- c api 的 SDK
- ZLMediaKit也提供c的api二次开发sdk库,头文件在`ZLMediaKit/api/include`,库文件为:
+ ZLMediaKit 也提供 c 的 api 二次开发 sdk 库,头文件在`ZLMediaKit/api/include`,库文件为:
- - linux下:
+ - linux 下:
```sh
ZLMediaKit/release/linux/Debug/libmk_api.so
```
- - macOS下:
+ - macOS 下:
```sh
ZLMediaKit/release/linux/mac/libmk_api.dylib
```
- - windows下:
+ - windows 下:
```sh
ZLMediaKit/release/windows/Debug/mk_api.dll
ZLMediaKit/release/windows/Debug/mk_api.lib
```
- SDK头文件有详细的注释,一般足够二次开发使用。
-
-
+ SDK 头文件有详细的注释,一般足够二次开发使用。
- 以`test_`开头的测试程序
相关代码在`ZLMediaKit/tests`目录下,你可以对照代码启动测试进程。
-
-
## 8、测试
请参考[此文章](../guide/media_server/push_test.md)完成推流播放测试
-