diff --git a/.gitignore b/.gitignore
index d911e40..14a3ee9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ npm-debug.log*
# Dependency directories
bower_components/
node_modules/
+hls-fetcher/
# Build-related directories
dist/
diff --git a/package-lock.json b/package-lock.json
index 063afb1..d740ede 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,14 @@
"js-tokens": "^4.0.0"
}
},
+ "@babel/runtime": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
+ "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
"@samverschueren/stream-to-observable": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
@@ -34,9 +42,9 @@
}
},
"@textlint/ast-node-types": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.3.tgz",
- "integrity": "sha512-5zqbMpeWk1B3AUkAmI5d3Y6CWqQNXeLKbdOGkwkvM0NSvhnlpAVooJ348lyfk8AwEQwzRVtAacQVXmIhdCwLGA==",
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-4.2.4.tgz",
+ "integrity": "sha512-ggiixpScxgdMY42b6UafD1iUboSvl9k3vGA9kynP+kd6mEhTDzxtb1aHPDAnV+DpAEw4qpHMz72GBFkX/iOSFw==",
"dev": true
},
"@textlint/markdown-to-ast": {
@@ -54,6 +62,16 @@
"unified": "^6.1.6"
}
},
+ "@videojs/vhs-utils": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-1.1.0.tgz",
+ "integrity": "sha512-J+1rLDj3iA1qejmCU3b+UOdTpT9w00XaxyJis+JUfTOZ5o5t8BHa5Uhmk8pXDNsjSJNJyMMgtJ6+z8g/Fxsuzg==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "global": "^4.3.2",
+ "url-toolkit": "^2.1.6"
+ }
+ },
"JSONStream": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
@@ -77,9 +95,9 @@
"dev": true
},
"acorn-jsx": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
- "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz",
+ "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
"dev": true
},
"add-stream": {
@@ -89,13 +107,14 @@
"dev": true
},
"aes-decrypter": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.0.tgz",
- "integrity": "sha1-eEihwUW5/b9Xrj4rWxvHzwZEqPs=",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-3.0.1.tgz",
+ "integrity": "sha512-bnuOEvfgTucocsfx9RAxv9S91lJhFkQsTqDCVnhV4BXk6baO+WOLeipdPTiBNg8QyikBWRuJry7Rf9oY6OWy9A==",
"requires": {
- "commander": "^2.9.0",
+ "@babel/runtime": "^7.5.5",
+ "@videojs/vhs-utils": "^1.0.0",
"global": "^4.3.2",
- "pkcs7": "^1.0.2"
+ "pkcs7": "^1.0.3"
}
},
"ajv": {
@@ -736,7 +755,8 @@
"commander": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
- "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
+ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+ "dev": true
},
"comment-parser": {
"version": "0.5.5",
@@ -811,22 +831,22 @@
}
},
"conventional-changelog": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.9.tgz",
- "integrity": "sha512-JbNVm1iGZ3aXxcFZjqKNDNfdgchQjSltWc8rvSniMrkHLsub9Wn20/JLdJNTBM74dt1IA2M+v/mzServ6N37YA==",
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.10.tgz",
+ "integrity": "sha512-6RDj31hL39HUkpqvPjRlOxAwJRwur8O2qu9m6R0FBNDGwCJyy4SYH9NfyshozxYSeklrauKRf3oSbyoEZVzu9Q==",
"dev": true,
"requires": {
"conventional-changelog-angular": "^5.0.3",
"conventional-changelog-atom": "^2.0.1",
"conventional-changelog-codemirror": "^2.0.1",
- "conventional-changelog-conventionalcommits": "^4.0.0",
- "conventional-changelog-core": "^3.2.3",
+ "conventional-changelog-conventionalcommits": "^4.1.0",
+ "conventional-changelog-core": "^4.0.0",
"conventional-changelog-ember": "^2.0.2",
"conventional-changelog-eslint": "^3.0.2",
"conventional-changelog-express": "^2.0.1",
"conventional-changelog-jquery": "^3.0.4",
"conventional-changelog-jshint": "^2.0.1",
- "conventional-changelog-preset-loader": "^2.1.1"
+ "conventional-changelog-preset-loader": "^2.2.0"
}
},
"conventional-changelog-angular": {
@@ -849,14 +869,14 @@
}
},
"conventional-changelog-cli": {
- "version": "2.0.22",
- "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.0.22.tgz",
- "integrity": "sha512-aLUQmyomfXV0xauIpQtsLPXnqZMumm4+1P6Mv2CjrlKF8XQ8Jn1LnMUScaLnqvDOzeGIMwPIY5DVA7hGFD6ddw==",
+ "version": "2.0.23",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-cli/-/conventional-changelog-cli-2.0.23.tgz",
+ "integrity": "sha512-a/jDZHEUpSHQMAqeDrmrFhz9CKHBKhBGpJyc38BCfNjFA1RKchpq/Qqbo1BZwRLWrW/PX7IGsUicTyhniqUH9g==",
"dev": true,
"requires": {
"add-stream": "^1.0.0",
- "conventional-changelog": "^3.1.9",
- "lodash": "^4.2.1",
+ "conventional-changelog": "^3.1.10",
+ "lodash": "^4.14.14",
"meow": "^4.0.0",
"tempfile": "^1.1.1"
}
@@ -871,9 +891,9 @@
}
},
"conventional-changelog-conventionalcommits": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.0.0.tgz",
- "integrity": "sha512-hPkVd+OXFqXhKgi/D2i4+lCbAtI7RqzDtAb7MhDsTer2pNA7mmkrwNdN6ph3iC/r3F0Wf10JYheEElRf/Q5qJw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.1.0.tgz",
+ "integrity": "sha512-J3xolGrH8PTxpCqueHOuZtv3Cp73SQOWiBQzlsaugZAZ+hZgcJBonmC+1bQbfGs2neC2S18p2L1Gx+nTEglJTQ==",
"dev": true,
"requires": {
"compare-func": "^1.3.1",
@@ -881,18 +901,18 @@
}
},
"conventional-changelog-core": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz",
- "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.0.0.tgz",
+ "integrity": "sha512-+bZMeBUdjKxfyX2w6EST9U7zb85wxrGS3IV4H7SqPya44osNQbm3P+vyqfLs6s57FkoEamC93ioDEiguVLWmSQ==",
"dev": true,
"requires": {
- "conventional-changelog-writer": "^4.0.6",
+ "conventional-changelog-writer": "^4.0.7",
"conventional-commits-parser": "^3.0.3",
"dateformat": "^3.0.0",
"get-pkg-repo": "^1.0.0",
"git-raw-commits": "2.0.0",
"git-remote-origin-url": "^2.0.0",
- "git-semver-tags": "^2.0.3",
+ "git-semver-tags": "^3.0.0",
"lodash": "^4.2.1",
"normalize-package-data": "^2.3.5",
"q": "^1.5.1",
@@ -948,9 +968,9 @@
}
},
"conventional-changelog-preset-loader": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.1.1.tgz",
- "integrity": "sha512-K4avzGMLm5Xw0Ek/6eE3vdOXkqnpf9ydb68XYmCc16cJ99XMMbc2oaNMuPwAsxVK6CC1yA4/I90EhmWNj0Q6HA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.2.0.tgz",
+ "integrity": "sha512-zXB+5vF7D5Y3Cb/rJfSyCCvFphCVmF8mFqOdncX3BmjZwAtGAPfYrBcT225udilCKvBbHgyzgxqz2GWDB5xShQ==",
"dev": true
},
"conventional-changelog-videojs": {
@@ -965,15 +985,15 @@
}
},
"conventional-changelog-writer": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.6.tgz",
- "integrity": "sha512-ou/sbrplJMM6KQpR5rKFYNVQYesFjN7WpNGdudQSWNi6X+RgyFUcSv871YBYkrUYV9EX8ijMohYVzn9RUb+4ag==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.7.tgz",
+ "integrity": "sha512-p/wzs9eYaxhFbrmX/mCJNwJuvvHR+j4Fd0SQa2xyAhYed6KBiZ780LvoqUUvsayP4R1DtC27czalGUhKV2oabw==",
"dev": true,
"requires": {
"compare-func": "^1.3.1",
"conventional-commits-filter": "^2.0.2",
"dateformat": "^3.0.0",
- "handlebars": "^4.1.0",
+ "handlebars": "^4.1.2",
"json-stringify-safe": "^5.0.1",
"lodash": "^4.2.1",
"meow": "^4.0.0",
@@ -1044,9 +1064,9 @@
},
"dependencies": {
"semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
@@ -1150,10 +1170,18 @@
}
},
"deep-equal": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
- "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
- "dev": true
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
+ "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
+ "dev": true,
+ "requires": {
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.2.0"
+ }
},
"deep-is": {
"version": "0.1.3",
@@ -1161,6 +1189,15 @@
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
"dev": true
},
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
"define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
@@ -1251,13 +1288,27 @@
}
},
"dom-serializer": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
- "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz",
+ "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==",
"dev": true,
"requires": {
- "domelementtype": "^1.3.0",
- "entities": "^1.1.1"
+ "domelementtype": "^2.0.1",
+ "entities": "^2.0.0"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
+ "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
+ "dev": true
+ },
+ "entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
+ "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
+ "dev": true
+ }
}
},
"dom-walk": {
@@ -1444,9 +1495,9 @@
}
},
"inquirer": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz",
- "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==",
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
+ "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.2.0",
@@ -1506,9 +1557,9 @@
"dev": true
},
"semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"string-width": {
@@ -1589,18 +1640,18 @@
}
},
"eslint-utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz",
- "integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
+ "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.0.0"
}
},
"eslint-visitor-keys": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
- "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
+ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"dev": true
},
"espree": {
@@ -1615,9 +1666,9 @@
},
"dependencies": {
"acorn": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
- "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
+ "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
"dev": true
}
}
@@ -1647,15 +1698,15 @@
}
},
"estraverse": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
- "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"execa": {
@@ -1989,6 +2040,12 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
"functional-red-black-tree": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
@@ -2346,9 +2403,9 @@
}
},
"git-semver-tags": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz",
- "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-3.0.0.tgz",
+ "integrity": "sha512-T4C/gJ9k2Bnxz+PubtcyiMtUUKrC+Nh9Q4zaECcnmVMwJgPhrNyP/Rf+YpdRqsJbCV/+kYrCH24Xg+IeAmbOPg==",
"dev": true,
"requires": {
"meow": "^4.0.0",
@@ -2400,9 +2457,9 @@
"dev": true
},
"graceful-fs": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
- "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==",
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
"dev": true
},
"growl": {
@@ -2437,6 +2494,15 @@
"har-schema": "^2.0.0"
}
},
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
@@ -2511,9 +2577,9 @@
"dev": true
},
"hosted-git-info": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
- "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz",
+ "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==",
"dev": true
},
"htmlparser2": {
@@ -2616,9 +2682,9 @@
}
},
"p-limit": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
- "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
@@ -2833,6 +2899,12 @@
"is-decimal": "^1.0.0"
}
},
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
+ "dev": true
+ },
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -2874,6 +2946,12 @@
}
}
},
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
"is-decimal": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz",
@@ -3006,6 +3084,15 @@
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
"is-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
@@ -3532,10 +3619,12 @@
}
},
"m3u8-parser": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.0.tgz",
- "integrity": "sha512-iH2AygTFILtato+XAgnoPYzLHM4R3DjATj7Ozbk7EHdB2XoLF2oyOUguM7Kc4UVHbQHHL/QPaw98r7PbWzG0gg==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-4.4.2.tgz",
+ "integrity": "sha512-4JJ163xdmyBjyHIH+OzdT9ATpgLcBulW8tD/aLEcJ8vXxrmonQWjAAOXQ/0szRE3IJkh+ECTrZjOBRH/Ii77cw==",
"requires": {
+ "@babel/runtime": "^7.5.5",
+ "@videojs/vhs-utils": "^1.1.0",
"global": "^4.3.2"
}
},
@@ -3752,6 +3841,17 @@
"integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==",
"dev": true
},
+ "mpd-parser": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-0.9.0.tgz",
+ "integrity": "sha512-odcncZQorJk6EgdiLOUkHeKMtABbCMiKpxMAtPN5T0xoNL/7qzO5fmPkNmsHsBccQg/3vOg9XXHadS/dIenHBg==",
+ "requires": {
+ "@babel/runtime": "^7.5.5",
+ "@videojs/vhs-utils": "^1.1.0",
+ "global": "^4.3.2",
+ "xmldom": "^0.1.27"
+ }
+ },
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -3834,9 +3934,9 @@
"dev": true
},
"semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
@@ -3901,9 +4001,9 @@
},
"dependencies": {
"semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
@@ -3918,9 +4018,9 @@
},
"dependencies": {
"semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
@@ -4416,6 +4516,18 @@
}
}
},
+ "object-is": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
+ "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
"object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -4665,17 +4777,20 @@
}
},
"pkcs7": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.2.tgz",
- "integrity": "sha1-ttulJ1KMKUK/wSLOLa/NteWQdOc="
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.3.tgz",
+ "integrity": "sha512-3MP+alokz148xIxdMpLovjxIUia1cMzxyJ6FjyZl2a1UPapjRk4Y8hni4KsZRGrdbD1woArGMKe/OsSB7ggzHQ==",
+ "requires": {
+ "@babel/runtime": "^7.5.5"
+ }
},
"pkg-can-install": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pkg-can-install/-/pkg-can-install-1.0.3.tgz",
- "integrity": "sha512-LRvLsj4XajSAf6RBO88H99SLEiDNeJ7lCF9rf42vQCCrmFtBEfbXflgJ5qRtwCdeA/Y+X3UYHoJkElT2BFEDGg==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/pkg-can-install/-/pkg-can-install-1.0.4.tgz",
+ "integrity": "sha512-we6BP4jR0ZQcDc9G9ptFvFJvYXoHlCT2PAinu98AotA4j8ZeazkUM/VSuFD4aQG3aPcuyBLLZJLxOEfzvEF7gw==",
"dev": true,
"requires": {
- "shelljs": "^0.8.2"
+ "shelljs": "^0.8.3"
}
},
"pkg-dir": {
@@ -4707,9 +4822,9 @@
}
},
"p-limit": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
- "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
@@ -4763,9 +4878,9 @@
}
},
"please-upgrade-node": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz",
- "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
+ "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
"dev": true,
"requires": {
"semver-compare": "^1.0.0"
@@ -4841,9 +4956,9 @@
"dev": true
},
"psl": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz",
- "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA=="
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz",
+ "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag=="
},
"pump": {
"version": "3.0.0",
@@ -4928,6 +5043,11 @@
"strip-indent": "^2.0.0"
}
},
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
+ },
"regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@@ -4938,6 +5058,15 @@
"safe-regex": "^1.1.0"
}
},
+ "regexp.prototype.flags": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
+ "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2"
+ }
+ },
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
@@ -5042,9 +5171,9 @@
}
},
"resolve": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
- "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
+ "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
@@ -5153,9 +5282,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"semver": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.2.0.tgz",
- "integrity": "sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"semver-compare": {
@@ -5559,20 +5688,12 @@
}
},
"string_decoder": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
- "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true,
"requires": {
- "safe-buffer": "~5.1.0"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- }
+ "safe-buffer": "~5.2.0"
}
},
"stringify-object": {
@@ -5660,9 +5781,9 @@
"dev": true
},
"table": {
- "version": "5.4.4",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.4.tgz",
- "integrity": "sha512-IIfEAUx5QlODLblLrGTTLJA7Tk0iLSGBvgY8essPRVNGHAzThujww1YqHLs6h3HfTg55h++RzLHH5Xw/rfv+mg==",
+ "version": "5.4.6",
+ "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+ "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
"dev": true,
"requires": {
"ajv": "^6.10.2",
@@ -6100,6 +6221,11 @@
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
"dev": true
},
+ "url-toolkit": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.1.6.tgz",
+ "integrity": "sha512-UaZ2+50am4HwrV2crR/JAf63Q4VvPYphe63WGeoJxeu8gmOm0qxPt+KsukfakPNrX9aymGNEkkaoICwn+OuvBw=="
+ },
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -6113,9 +6239,9 @@
"dev": true
},
"uuid": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
- "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
+ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"validate-npm-package-license": {
"version": "3.0.4",
@@ -6292,6 +6418,11 @@
"integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=",
"dev": true
},
+ "xmldom": {
+ "version": "0.1.27",
+ "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
+ "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk="
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index 38ac59f..5b9f892 100644
--- a/package.json
+++ b/package.json
@@ -33,8 +33,9 @@
"aes-decrypter": "^3.0.0",
"bluebird": "^3.4.0",
"filenamify": "^4.1.0",
- "m3u8-parser": "^4.3.0",
+ "m3u8-parser": "^4.4.2",
"mkdirp": "^0.5.1",
+ "mpd-parser": "^0.9.0",
"pessimist": "^0.3.5",
"request": "^2.87.0",
"requestretry": "^2.0.0"
diff --git a/src/walk-manifest.js b/src/walk-manifest.js
index 0113bff..055ed3e 100644
--- a/src/walk-manifest.js
+++ b/src/walk-manifest.js
@@ -1,5 +1,6 @@
/* eslint-disable no-console */
const m3u8 = require('m3u8-parser');
+const mpd = require('mpd-parser');
const request = require('requestretry');
const url = require('url');
const path = require('path');
@@ -55,7 +56,7 @@ const mediaGroupPlaylists = function(mediaGroups) {
return playlists;
};
-const parseManifest = function(content) {
+const parseM3u8Manifest = function(content) {
const parser = new m3u8.Parser();
parser.push(content);
@@ -63,11 +64,55 @@ const parseManifest = function(content) {
return parser.manifest;
};
+const collectPlaylists = function(parsed) {
+ return []
+ .concat(parsed.playlists || [])
+ .concat(mediaGroupPlaylists(parsed.mediaGroups || {}) || [])
+ .reduce(function(acc, p) {
+ acc.push(p);
+
+ if (p.playlists) {
+ acc = acc.concat(collectPlaylists(p));
+ }
+ return acc;
+ }, []);
+};
+
+const parseMpdManifest = function(content, srcUrl) {
+ const mpdPlaylists = mpd.toPlaylists(mpd.inheritAttributes(mpd.stringToMpdXml(content), {
+ manifestUri: srcUrl
+ }));
+
+ const m3u8Result = mpd.toM3u8(mpdPlaylists);
+ const m3u8Playlists = collectPlaylists(m3u8Result);
+
+ m3u8Playlists.forEach(function(m) {
+ const mpdPlaylist = m.attributes && mpdPlaylists.find(function(p) {
+ return p.attributes.id === m.attributes.NAME;
+ });
+
+ if (mpdPlaylist) {
+ m.dashattributes = mpdPlaylist.attributes;
+ }
+ // add sidx to segments
+ if (m.sidx) {
+ // fix init segment map if it has one
+ if (m.sidx.map && !m.sidx.map.uri) {
+ m.sidx.map.uri = m.sidx.map.resolvedUri;
+ }
+
+ m.segments.push(m.sidx);
+ }
+ });
+
+ return m3u8Result;
+};
+
const parseKey = function(requestOptions, basedir, decrypt, resources, manifest, parent) {
return new Promise(function(resolve, reject) {
if (!manifest.parsed.segments[0] || !manifest.parsed.segments[0].key) {
- resolve({});
+ return resolve({});
}
const key = manifest.parsed.segments[0].key;
@@ -92,7 +137,7 @@ const parseKey = function(requestOptions, basedir, decrypt, resources, manifest,
));
key.uri = keyUri;
resources.push(key);
- resolve(key);
+ return resolve(key);
}
requestOptions.url = keyUri;
@@ -155,17 +200,21 @@ const walkPlaylist = function(options) {
visitedUrls = [],
requestTimeout = 1500,
requestRetryMaxAttempts = 5,
+ dashPlaylist = null,
requestRetryDelay = 5000
} = options;
let resources = [];
- const manifest = {};
+ const manifest = {parent};
manifest.uri = uri;
manifest.file = path.join(basedir, fsSanitize(path.basename(uri)));
// if we are not the master playlist
- if (parent) {
+ if (dashPlaylist && parent) {
+ manifest.file = parent.file;
+ manifest.uri = parent.uri;
+ } else if (parent) {
manifest.file = path.join(
path.dirname(parent.file),
'manifest' + manifestIndex,
@@ -179,101 +228,124 @@ const walkPlaylist = function(options) {
parent.content = Buffer.from(parent.content.toString().replace(uri, path.relative(path.dirname(parent.file), manifest.file)));
}
- if (visitedUrls.includes(manifest.uri)) {
+ if (!dashPlaylist && visitedUrls.includes(manifest.uri)) {
console.error(`[WARN] Trying to visit the same uri again; skipping to avoid getting stuck in a cycle: ${manifest.uri}`);
return resolve(resources);
}
- request({
- url: manifest.uri,
- timeout: requestTimeout,
- maxAttempts: requestRetryMaxAttempts,
- retryDelay: requestRetryDelay
- })
- .then(function(response) {
- if (response.statusCode !== 200) {
- const manifestError = new Error(response.statusCode + '|' + manifest.uri);
+ let requestPromise;
- manifestError.reponse = response;
- return onError(manifestError, manifest.uri, resources, resolve, reject);
- }
- // Only push manifest uris that get a non 200 and don't timeout
+ if (dashPlaylist) {
+ requestPromise = Promise.resolve({statusCode: 200});
+ } else {
+ requestPromise = request({
+ url: manifest.uri,
+ timeout: requestTimeout,
+ maxAttempts: requestRetryMaxAttempts,
+ retryDelay: requestRetryDelay
+ });
+ }
+
+ requestPromise.then(function(response) {
+ if (response.statusCode !== 200) {
+ const manifestError = new Error(response.statusCode + '|' + manifest.uri);
+
+ manifestError.reponse = response;
+ return onError(manifestError, manifest.uri, resources, resolve, reject);
+ }
+ // Only push manifest uris that get a non 200 and don't timeout
+ let dash;
+
+ if (!dashPlaylist) {
resources.push(manifest);
visitedUrls.push(manifest.uri);
manifest.content = response.body;
+ if ((/^application\/dash\+xml/i).test(response.headers['content-type']) || (/^\<\?xml/i).test(response.body)) {
+ dash = true;
+ manifest.parsed = parseMpdManifest(manifest.content, manifest.uri);
+ } else {
+ manifest.parsed = parseM3u8Manifest(manifest.content);
+ }
+ } else {
+ dash = true;
+ manifest.parsed = dashPlaylist;
+ }
- manifest.parsed = parseManifest(manifest.content);
- manifest.parsed.segments = manifest.parsed.segments || [];
- manifest.parsed.playlists = manifest.parsed.playlists || [];
- manifest.parsed.mediaGroups = manifest.parsed.mediaGroups || {};
+ manifest.parsed.segments = manifest.parsed.segments || [];
+ manifest.parsed.playlists = manifest.parsed.playlists || [];
+ manifest.parsed.mediaGroups = manifest.parsed.mediaGroups || {};
- const initSegments = [];
+ const initSegments = [];
- manifest.parsed.segments.forEach(function(s) {
- if (s.map && s.map.uri && !initSegments.some((m) => s.map.uri === m.uri)) {
- manifest.parsed.segments.push(s.map);
- initSegments.push(s.map);
+ manifest.parsed.segments.forEach(function(s) {
+ if (s.map && s.map.uri && !initSegments.some((m) => s.map.uri === m.uri)) {
+ manifest.parsed.segments.push(s.map);
+ initSegments.push(s.map);
+ }
+ });
+
+ const playlists = manifest.parsed.playlists.concat(mediaGroupPlaylists(manifest.parsed.mediaGroups));
+
+ parseKey({
+ time: requestTimeout,
+ maxAttempts: requestRetryMaxAttempts,
+ retryDelay: requestRetryDelay
+ }, basedir, decrypt, resources, manifest, parent).then(function(key) {
+ // SEGMENTS
+ manifest.parsed.segments.forEach(function(s, i) {
+ if (!s.uri) {
+ return;
}
- });
+ // put segments in manifest-name/segment-name.ts
+ s.file = path.join(path.dirname(manifest.file), fsSanitize(path.basename(s.uri)));
- const playlists = manifest.parsed.playlists.concat(mediaGroupPlaylists(manifest.parsed.mediaGroups));
-
- parseKey({
- time: requestTimeout,
- maxAttempts: requestRetryMaxAttempts,
- retryDelay: requestRetryDelay
- }, basedir, decrypt, resources, manifest, parent).then(function(key) {
- // SEGMENTS
- manifest.parsed.segments.forEach(function(s, i) {
- if (!s.uri) {
- return;
- }
- // put segments in manifest-name/segment-name.ts
- s.file = path.join(path.dirname(manifest.file), fsSanitize(path.basename(s.uri)));
- if (!isAbsolute(s.uri)) {
- s.uri = joinURI(path.dirname(manifest.uri), s.uri);
- }
- if (key) {
- s.key = key;
- s.key.iv = s.key.iv || new Uint32Array([0, 0, 0, manifest.parsed.mediaSequence, i]);
- }
+ if (!isAbsolute(s.uri)) {
+ s.uri = joinURI(path.dirname(manifest.uri), s.uri);
+ }
+ if (key) {
+ s.key = key;
+ s.key.iv = s.key.iv || new Uint32Array([0, 0, 0, manifest.parsed.mediaSequence, i]);
+ }
+ if (manifest.content) {
manifest.content = Buffer.from(manifest.content.toString().replace(
s.uri,
path.relative(path.dirname(manifest.file), s.file)
));
- resources.push(s);
- });
+ }
+ resources.push(s);
+ });
- // SUB Playlists
- const subs = playlists.map(function(p, z) {
- if (!p.uri) {
- return Promise().resolve(resources);
- }
- return walkPlaylist({
- decrypt,
- basedir,
- uri: p.uri,
- parent: manifest,
- manifestIndex: z,
- onError,
- visitedUrls,
- requestTimeout,
- requestRetryMaxAttempts,
- requestRetryDelay
- });
+ // SUB Playlists
+ const subs = playlists.map(function(p, z) {
+ if (!p.uri && !dash) {
+ return Promise.resolve(resources);
+ }
+ return walkPlaylist({
+ dashPlaylist: dash ? p : null,
+ decrypt,
+ basedir,
+ uri: p.uri,
+ parent: manifest,
+ manifestIndex: z,
+ onError,
+ visitedUrls,
+ requestTimeout,
+ requestRetryMaxAttempts,
+ requestRetryDelay
});
+ });
- Promise.all(subs).then(function(r) {
- const flatten = [].concat.apply([], r);
+ Promise.all(subs).then(function(r) {
+ const flatten = [].concat.apply([], r);
- resources = resources.concat(flatten);
- resolve(resources);
- }).catch(function(err) {
- onError(err, manifest.uri, resources, resolve, reject);
- });
+ resources = resources.concat(flatten);
+ resolve(resources);
+ }).catch(function(err) {
+ onError(err, manifest.uri, resources, resolve, reject);
});
- })
+ });
+ })
.catch(function(err) {
onError(err, manifest.uri, resources, resolve, reject);
});
diff --git a/src/write-data.js b/src/write-data.js
index dc2d84b..0153e5b 100644
--- a/src/write-data.js
+++ b/src/write-data.js
@@ -35,25 +35,19 @@ const requestFile = function(uri) {
});
};
-const toArrayBuffer = function(buffer) {
- const ab = new ArrayBuffer(buffer.length);
- const view = new Uint8Array(ab);
-
- for (let i = 0; i < buffer.length; ++i) {
- view[i] = buffer[i];
- }
- return ab;
+const toUint8Array = function(nodeBuffer) {
+ return new Uint8Array(nodeBuffer.buffer, nodeBuffer.byteOffset, nodeBuffer.byteLength / Uint8Array.BYTES_PER_ELEMENT);
};
const decryptFile = function(content, encryption) {
return new Promise(function(resolve, reject) {
/* eslint-disable no-new */
// this is how you use it, its kind of bad but :shrug:
- new AesDecrypter(toArrayBuffer(content), encryption.bytes, encryption.iv, function(err, bytes) {
+ new AesDecrypter(toUint8Array(content), encryption.bytes, encryption.iv, function(err, bytes) {
if (err) {
return reject(err);
}
- return resolve(new Buffer(bytes));
+ return resolve(Buffer.from(bytes));
});
/* eslint-enable no-new */
});
@@ -68,7 +62,7 @@ const WriteData = function(decrypt, concurrency, resources) {
operations.push(function() {
return writeFile(r.file, r.content);
});
- } else if (r.key && decrypt) {
+ } else if (r.uri && r.key && decrypt) {
operations.push(function() {
return requestFile(r.uri).then(function(content) {
return decryptFile(content, r.key);
@@ -76,7 +70,7 @@ const WriteData = function(decrypt, concurrency, resources) {
return writeFile(r.file, content);
});
});
- } else if (inProgress.indexOf(r.uri) === -1) {
+ } else if (r.uri && inProgress.indexOf(r.uri) === -1) {
operations.push(function() {
return requestFile(r.uri).then(function(content) {
return writeFile(r.file, content);
diff --git a/test/resources/dash.mpd b/test/resources/dash.mpd
new file mode 100644
index 0000000..0e92f34
--- /dev/null
+++ b/test/resources/dash.mpd
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/resources/sidx.mpd b/test/resources/sidx.mpd
new file mode 100644
index 0000000..2092d57
--- /dev/null
+++ b/test/resources/sidx.mpd
@@ -0,0 +1,32 @@
+
+
+ ./
+
+
+
+ German_Forest_SHORT_1v0-avc1.42c01e-68s-848x476-h264-1500000bps_seg.mp4
+
+
+
+
+
+
+
+
+ German_Forest_Short_Poem_english-en-68s-2-lc-128000bps_seg.mp4
+
+
+
+
+
+
+
+
+ German_Forest_Short_Poem_german-de-68s-2-lc-128000bps_seg.mp4
+
+
+
+
+
+
+
diff --git a/test/unit/walk-manifest.spec.js b/test/unit/walk-manifest.spec.js
index 6164d06..eeaab37 100644
--- a/test/unit/walk-manifest.spec.js
+++ b/test/unit/walk-manifest.spec.js
@@ -149,12 +149,10 @@ describe('walk-manifest', function() {
assert.equal(setResources.size, 13);
setResources.forEach(function(item) {
- assert(
- item.uri.includes('.ts') ||
+ assert(item.uri.includes('.ts') ||
item.uri.includes('.m3u8') ||
item.uri.includes('.mp4') ||
- item.uri.includes('.m4s')
- );
+ item.uri.includes('.m4s'));
});
@@ -628,5 +626,75 @@ describe('walk-manifest', function() {
done();
});
});
+
+ it('should return segments and playlists for mpd', function() {
+ nock(TEST_URL)
+ .get('/dash.mpd')
+ .replyWithFile(200, `${process.cwd()}/test/resources/dash.mpd`);
+
+ const options = {decrypt: false, basedir: '.', uri: TEST_URL + '/dash.mpd', requestRetryMaxAttempts: 0};
+
+ return walker(options)
+ .then(function(resources) {
+ // m3u8 and 13 segments
+ const setResources = new Set(resources);
+ const count = {mp4: 0, m4v: 0, m4a: 0, mpd: 0};
+
+ assert.equal(setResources.size, 37);
+ setResources.forEach(function(item) {
+ if (item.uri.includes('.mp4')) {
+ count.mp4 += 1;
+ } else if (item.uri.includes('.m4v')) {
+ count.m4v += 1;
+ } else if (item.uri.includes('.m4a')) {
+ count.m4a += 1;
+ } else if (item.uri.includes('.mpd')) {
+ count.mpd += 1;
+ } else {
+ assert(false, `items uri ${item.uri} was unexpected`);
+ return;
+ }
+
+ assert(true, 'items uri was expected');
+ });
+
+ assert.equal(count.mp4, 6, 'mp4 count as expected');
+ assert.equal(count.mpd, 1, 'mpd count as expected');
+ assert.equal(count.m4v, 25, 'm4v count as expected');
+ assert.equal(count.m4a, 5, 'm4a count as expected');
+ });
+ });
+ });
+
+ it('should return segments and playlists for mpd with sidx', function() {
+ nock(TEST_URL)
+ .get('/sidx.mpd')
+ .replyWithFile(200, `${process.cwd()}/test/resources/sidx.mpd`);
+
+ const options = {decrypt: false, basedir: '.', uri: TEST_URL + '/sidx.mpd', requestRetryMaxAttempts: 0};
+
+ return walker(options)
+ .then(function(resources) {
+ // m3u8 and 13 segments
+ const setResources = new Set(resources);
+ const count = {mp4: 0, m4v: 0, m4a: 0, mpd: 0};
+
+ assert.equal(setResources.size, 7);
+ setResources.forEach(function(item) {
+ if (item.uri.includes('.mp4')) {
+ count.mp4 += 1;
+ } else if (item.uri.includes('.mpd')) {
+ count.mpd += 1;
+ } else {
+ assert(false, `items uri ${item.uri} was unexpected`);
+ return;
+ }
+
+ assert(true, 'items uri was expected');
+ });
+
+ assert.equal(count.mp4, 6, 'mp4 count as expected');
+ assert.equal(count.mpd, 1, 'mpd count as expected');
+ });
});
});