From 677af3712bbf5748277a5d88d85fb0cf719210b9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 16 Sep 2021 19:35:35 +0000
Subject: [PATCH 01/15] Bump axios from 0.21.1 to 0.21.2 in /backend
Bumps [axios](https://github.com/axios/axios) from 0.21.1 to 0.21.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.21.1...v0.21.2)
---
updated-dependencies:
- dependency-name: axios
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
backend/package-lock.json | 14 +++++++-------
backend/package.json | 2 +-
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/backend/package-lock.json b/backend/package-lock.json
index f68e7c4..63a7e66 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -316,11 +316,11 @@
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
},
"axios": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
- "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz",
+ "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==",
"requires": {
- "follow-redirects": "^1.10.0"
+ "follow-redirects": "^1.14.0"
}
},
"backoff": {
@@ -1267,9 +1267,9 @@
}
},
"follow-redirects": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
- "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
+ "version": "1.14.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
+ "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g=="
},
"forever-agent": {
"version": "0.6.1",
diff --git a/backend/package.json b/backend/package.json
index 8d4579d..ac96767 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -33,7 +33,7 @@
"archiver": "^3.1.1",
"async": "^3.1.0",
"async-mutex": "^0.3.1",
- "axios": "^0.21.1",
+ "axios": "^0.21.2",
"bcryptjs": "^2.4.0",
"compression": "^1.7.4",
"config": "^3.2.3",
From 1e9eec1b553c534e57afdb3290c9ef54dd9ee5a6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 16 Sep 2021 19:36:01 +0000
Subject: [PATCH 02/15] Bump electron from 8.2.0 to 9.4.0
Bumps [electron](https://github.com/electron/electron) from 8.2.0 to 9.4.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v8.2.0...v9.4.0)
Signed-off-by: dependabot[bot]
---
package-lock.json | 165 +++++++++++++++++++++-------------------------
package.json | 2 +-
2 files changed, 75 insertions(+), 92 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 2ac2dfa..cad23bd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1622,9 +1622,9 @@
}
},
"@electron/get": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.9.0.tgz",
- "integrity": "sha512-OBIKtF6ttIJotDXe4KJMUyTBO4xMii+mFjlA8R4CORuD4HvCUaCK3lPjhdTRCvuEv6gzWNbAvd9DNBv0v780lw==",
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.13.0.tgz",
+ "integrity": "sha512-+SjZhRuRo+STTO1Fdhzqnv9D2ZhjxXP6egsJ9kiO8dtP68cDx7dFCwWi64dlMQV7sWcfW1OYCW4wviEBzmRsfQ==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -1634,7 +1634,7 @@
"global-tunnel-ng": "^2.7.1",
"got": "^9.6.0",
"progress": "^2.0.3",
- "sanitize-filename": "^1.6.2",
+ "semver": "^6.2.0",
"sumchecker": "^3.0.1"
},
"dependencies": {
@@ -1648,6 +1648,12 @@
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
}
}
},
@@ -3015,9 +3021,9 @@
"dev": true
},
"boolean": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz",
- "integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.4.tgz",
+ "integrity": "sha512-3hx0kwU3uzG6ReQ3pnaFQPSktpBw6RHN3/ivDKEuU8g1XSfafowyvDnadjv1xp8IZqhtSukxlwv9bF6FhX8m0w==",
"dev": true,
"optional": true
},
@@ -3298,9 +3304,9 @@
},
"dependencies": {
"get-stream": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz",
- "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dev": true,
"requires": {
"pump": "^3.0.0"
@@ -3313,9 +3319,9 @@
"dev": true
},
"normalize-url": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
- "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==",
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
"dev": true
}
}
@@ -3774,9 +3780,9 @@
}
},
"config-chain": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz",
- "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==",
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"dev": true,
"optional": true,
"requires": {
@@ -4799,9 +4805,9 @@
"dev": true
},
"electron": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/electron/-/electron-8.2.0.tgz",
- "integrity": "sha512-mnV43gKCrCUMHLmGws/DU/l8LhaxrFD53A4ofwtthdCqOZWGIdk1+eMphiVumXR5a3lC64XVvmXQ2k28i7F/zw==",
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-9.4.0.tgz",
+ "integrity": "sha512-hOC4q0jkb+UDYZRy8vrZ1IANnq+jznZnbkD62OEo06nU+hIbp2IrwDRBNuSLmQ3cwZMVir0WSIA1qEVK0PkzGA==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@@ -5007,9 +5013,9 @@
"dev": true
},
"env-paths": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz",
- "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==",
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true
},
"err-code": {
@@ -6276,34 +6282,37 @@
}
},
"global-agent": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.8.tgz",
- "integrity": "sha512-VpBe/rhY6Rw2VDOTszAMNambg+4Qv8j0yiTNDYEXXXxkUNGWLHp8A3ztK4YDBbFNcWF4rgsec6/5gPyryya/+A==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz",
+ "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==",
"dev": true,
"optional": true,
"requires": {
- "boolean": "^3.0.0",
- "core-js": "^3.6.4",
+ "boolean": "^3.0.1",
+ "core-js": "^3.6.5",
"es6-error": "^4.1.1",
- "matcher": "^2.1.0",
- "roarr": "^2.15.2",
- "semver": "^7.1.2",
- "serialize-error": "^5.0.0"
+ "matcher": "^3.0.0",
+ "roarr": "^2.15.3",
+ "semver": "^7.3.2",
+ "serialize-error": "^7.0.1"
},
"dependencies": {
"core-js": {
- "version": "3.6.4",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
- "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==",
+ "version": "3.17.3",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.3.tgz",
+ "integrity": "sha512-lyvajs+wd8N1hXfzob1LdOCCHFU4bGMbqqmLn1Q4QlCpDqWPpGf+p0nj+LNrvDDG33j0hZXw2nsvvVpHysxyNw==",
"dev": true,
"optional": true
},
"semver": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz",
- "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
- "optional": true
+ "optional": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
}
}
},
@@ -6326,9 +6335,9 @@
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
},
"globalthis": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz",
- "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz",
+ "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==",
"dev": true,
"optional": true,
"requires": {
@@ -8427,19 +8436,19 @@
}
},
"matcher": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.1.0.tgz",
- "integrity": "sha512-o+nZr+vtJtgPNklyeUKkkH42OsK8WAfdgaJE2FNxcjLPg+5QbeEoT6vRj8Xq/iv18JlQ9cmKsEu0b94ixWf1YQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
+ "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
"dev": true,
"optional": true,
"requires": {
- "escape-string-regexp": "^2.0.0"
+ "escape-string-regexp": "^4.0.0"
},
"dependencies": {
"escape-string-regexp": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"optional": true
}
@@ -10662,6 +10671,12 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
+ "prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
+ "dev": true
+ },
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -11717,13 +11732,13 @@
}
},
"roarr": {
- "version": "2.15.2",
- "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.2.tgz",
- "integrity": "sha512-jmaDhK9CO4YbQAV8zzCnq9vjAqeO489MS5ehZ+rXmFiPFFE6B+S9KYO6prjmLJ5A0zY3QxVlQdrIya7E/azz/Q==",
+ "version": "2.15.4",
+ "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
+ "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
"dev": true,
"optional": true,
"requires": {
- "boolean": "^3.0.0",
+ "boolean": "^3.0.1",
"detect-node": "^2.0.4",
"globalthis": "^1.0.1",
"json-stringify-safe": "^5.0.1",
@@ -11810,15 +11825,6 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true
},
- "sanitize-filename": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
- "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
- "dev": true,
- "requires": {
- "truncate-utf8-bytes": "^1.0.0"
- }
- },
"sass": {
"version": "1.27.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.27.0.tgz",
@@ -12033,19 +12039,19 @@
}
},
"serialize-error": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz",
- "integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
+ "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
"dev": true,
"optional": true,
"requires": {
- "type-fest": "^0.8.0"
+ "type-fest": "^0.13.1"
},
"dependencies": {
"type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
"dev": true,
"optional": true
}
@@ -13403,15 +13409,6 @@
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
- "truncate-utf8-bytes": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
- "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=",
- "dev": true,
- "requires": {
- "utf8-byte-length": "^1.0.1"
- }
- },
"ts-md5": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/ts-md5/-/ts-md5-1.2.7.tgz",
@@ -13843,14 +13840,6 @@
"dev": true,
"requires": {
"prepend-http": "^2.0.0"
- },
- "dependencies": {
- "prepend-http": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
- "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=",
- "dev": true
- }
}
},
"use": {
@@ -13865,12 +13854,6 @@
"integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=",
"dev": true
},
- "utf8-byte-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
- "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=",
- "dev": true
- },
"util": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
diff --git a/package.json b/package.json
index ad1f6f9..57b692e 100644
--- a/package.json
+++ b/package.json
@@ -61,7 +61,7 @@
"@typescript-eslint/eslint-plugin": "^4.29.0",
"@typescript-eslint/parser": "^4.29.0",
"codelyzer": "^6.0.0",
- "electron": "^8.0.1",
+ "electron": "^9.4.0",
"eslint": "^7.32.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
From bd2443b1e94753a282d972c8a4d3064eaccc2464 Mon Sep 17 00:00:00 2001
From: GlassedSilver
Date: Sat, 18 Sep 2021 16:59:49 +0200
Subject: [PATCH 03/15] docker-compose.yml: Use YoutubeDL-Material nightly
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 62c33fc..2d0d73e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -15,7 +15,7 @@ services:
- ./users:/app/users
ports:
- "8998:17442"
- image: tzahi12345/youtubedl-material:latest
+ image: tzahi12345/youtubedl-material:nightly
ytdl-mongo-db:
image: mongo
ports:
From f7e0b3e86b58b8f55383c9f66845b2e217533f50 Mon Sep 17 00:00:00 2001
From: GlassedSilver
Date: Sat, 18 Sep 2021 17:22:11 +0200
Subject: [PATCH 04/15] =?UTF-8?q?[DRAFT!]=20Bump=20alpine:=20pinned=20'3.1?=
=?UTF-8?q?2'=20=E2=86=92=20'latest'?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Dockerfile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 0be5ff4..d2b9d75 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.12 as frontend
+FROM alpine:latest as frontend
RUN apk add --no-cache \
npm
@@ -15,7 +15,7 @@ RUN ng build --prod
#--------------#
-FROM alpine:3.12
+FROM alpine:latest
ENV UID=1000 \
GID=1000 \
From 176c99f813be95c0524b284b57c5890490b5d1d9 Mon Sep 17 00:00:00 2001
From: GlassedSilver
Date: Sat, 18 Sep 2021 17:41:25 +0200
Subject: [PATCH 05/15] Reference host-specific instructions
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index 8f6fdde..b452bec 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,10 @@ Alternatively, you can port forward the port specified in the config (defaults t
## Docker
+### Host-specific instructions
+
+If you're on a Synology NAS, unRAID or any other possible special case you can check if there's known issues or instructions both in the issue tracker and in the [Wiki!](https://github.com/Tzahi12345/YoutubeDL-Material/wiki#environment-specific-guideshelp)
+
### Setup
If you are looking to setup YoutubeDL-Material with Docker, this section is for you. And you're in luck! Docker setup is quite simple.
From 33f23c3ca9a04d9e3e5467fb4c664c5e210dcfab Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Sun, 19 Sep 2021 14:24:18 -0400
Subject: [PATCH 06/15] Fixed issue where youtube-dl autoupdates broke if
checkExistsWithTimeout failed the first time
---
backend/app.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/backend/app.js b/backend/app.js
index 173e6ed..7404f3c 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -837,7 +837,7 @@ async function checkExistsWithTimeout(filePath, timeout) {
fs.access(filePath, fs.constants.R_OK, function (err) {
if (!err) {
clearTimeout(timer);
- watcher.close();
+ if (watcher) watcher.close();
resolve();
}
});
@@ -847,7 +847,7 @@ async function checkExistsWithTimeout(filePath, timeout) {
var watcher = fs.watch(dir, function (eventType, filename) {
if (eventType === 'rename' && filename === basename) {
clearTimeout(timer);
- watcher.close();
+ if (watcher) watcher.close();
resolve();
}
});
From 759637c1cfa53d1304dd9afd72c221509fe6a278 Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Sun, 19 Sep 2021 14:29:12 -0400
Subject: [PATCH 07/15] Fixed issue where per-subscription custom args were not
being applied
---
backend/subscriptions.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/backend/subscriptions.js b/backend/subscriptions.js
index 244cb70..568d06e 100644
--- a/backend/subscriptions.js
+++ b/backend/subscriptions.js
@@ -329,7 +329,8 @@ function generateOptionsForSubscriptionDownload(sub, user_uid) {
selectedHeight: sub.maxQuality && sub.maxQuality !== 'best' ? sub.maxQuality : null,
customFileFolderPath: getAppendedBasePath(sub, basePath),
customOutput: sub.custom_output ? `${sub.custom_output}` : `${default_output}`,
- customArchivePath: path.join(__dirname, basePath, 'archives', sub.name)
+ customArchivePath: path.join(__dirname, basePath, 'archives', sub.name),
+ additionalArgs: sub.custom_args
}
return base_download_options;
From a71d9f5c7e1ba7c2ed3c3d3b96c8ee398baadcda Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Sun, 19 Sep 2021 14:44:02 -0400
Subject: [PATCH 08/15] Added tests for arg generation and laid some plumbing
for better arg simulation in the UI
---
backend/downloader.js | 6 +++---
backend/subscriptions.js | 3 ++-
backend/test/tests.js | 14 ++++++++++++++
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/backend/downloader.js b/backend/downloader.js
index ec43b5d..16aaaa8 100644
--- a/backend/downloader.js
+++ b/backend/downloader.js
@@ -190,7 +190,7 @@ async function collectInfo(download_uid) {
options.customFileFolderPath = user_path + path.sep;
}
- let args = await generateArgs(url, type, options, download['user_uid']);
+ let args = await exports.generateArgs(url, type, options, download['user_uid']);
// get video info prior to download
let info = await getVideoInfoByURL(url, args, download_uid);
@@ -209,7 +209,7 @@ async function collectInfo(download_uid) {
if (category && category['custom_output']) {
options.customOutput = category['custom_output'];
options.noRelativePath = true;
- args = await generateArgs(url, type, options, download['user_uid']);
+ args = await exports.generateArgs(url, type, options, download['user_uid']);
info = await getVideoInfoByURL(url, args, download_uid);
}
@@ -369,7 +369,7 @@ async function downloadQueuedFile(download_uid) {
// helper functions
-async function generateArgs(url, type, options, user_uid = null) {
+exports.generateArgs = async (url, type, options, user_uid = null) => {
const audioFolderPath = config_api.getConfigItem('ytdl_audio_folder_path');
const videoFolderPath = config_api.getConfigItem('ytdl_video_folder_path');
diff --git a/backend/subscriptions.js b/backend/subscriptions.js
index 568d06e..90b6873 100644
--- a/backend/subscriptions.js
+++ b/backend/subscriptions.js
@@ -543,5 +543,6 @@ module.exports = {
deleteSubscriptionFile : deleteSubscriptionFile,
getVideosForSub : getVideosForSub,
initialize : initialize,
- updateSubscriptionPropertyMultiple : updateSubscriptionPropertyMultiple
+ updateSubscriptionPropertyMultiple : updateSubscriptionPropertyMultiple,
+ generateOptionsForSubscriptionDownload: generateOptionsForSubscriptionDownload
}
diff --git a/backend/test/tests.js b/backend/test/tests.js
index 1824cff..99b79b2 100644
--- a/backend/test/tests.js
+++ b/backend/test/tests.js
@@ -293,6 +293,7 @@ describe('Downloader', function() {
const downloader_api = require('../downloader');
downloader_api.initialize(db_api);
const url = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
+ const sub_id = 'dc834388-3454-41bf-a618-e11cb8c7de1c';
const options = {
ui_uid: uuid(),
user: 'admin'
@@ -325,4 +326,17 @@ describe('Downloader', function() {
it('Pause file', async function() {
});
+
+ it('Generate args', async function() {
+ const args = await downloader_api.generateArgs(url, 'video', options);
+ console.log(args);
+ });
+
+ it('Generate args - subscription', async function() {
+ subscriptions_api.initialize(db_api, logger);
+ const sub = await subscriptions_api.getSubscription(sub_id);
+ const sub_options = subscriptions_api.generateOptionsForSubscriptionDownload(sub, 'admin');
+ const args = await downloader_api.generateArgs(url, 'video', sub_options, 'admin');
+ console.log(args);
+ });
});
From 27faff054e279cff94e11ca273c0d20f32919cfb Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Sun, 19 Sep 2021 14:56:32 -0400
Subject: [PATCH 09/15] Recent videos component now remembers sort order
between page reloads
---
.../components/recent-videos/recent-videos.component.ts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/app/components/recent-videos/recent-videos.component.ts b/src/app/components/recent-videos/recent-videos.component.ts
index d6ff044..251c41d 100644
--- a/src/app/components/recent-videos/recent-videos.component.ts
+++ b/src/app/components/recent-videos/recent-videos.component.ts
@@ -107,6 +107,12 @@ export class RecentVideosComponent implements OnInit {
this.fileTypeFilter = cached_file_type_filter;
}
+ const sort_order = localStorage.getItem('recent_videos_sort_order');
+
+ if (sort_order) {
+ this.descendingMode = sort_order === 'descending';
+ }
+
this.searchChangedSubject
.debounceTime(500)
.pipe(distinctUntilChanged()
@@ -145,6 +151,7 @@ export class RecentVideosComponent implements OnInit {
toggleModeChange() {
this.descendingMode = !this.descendingMode;
+ localStorage.setItem('recent_videos_sort_order', this.descendingMode ? 'descending' : 'ascending');
this.getAllFiles();
}
From 58a0dc4afe9c5150c5ab6a3bdbf86967a05b5d22 Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Mon, 20 Sep 2021 22:04:46 -0600
Subject: [PATCH 10/15] Version and commit info is now generated during
autobuilds and can be viewed in the about dialog
Prepared removal of JSON translations from repo to move towards XLIFF-only
---
.github/workflows/build.yml | 17 +++++++++++++++++
.github/workflows/docker-release.yml | 17 +++++++++++++++++
.github/workflows/docker.yml | 17 +++++++++++++++++
backend/app.js | 12 ++++++++++++
src/app/app.component.ts | 4 ++++
.../about-dialog/about-dialog.component.html | 11 +++++++++++
.../about-dialog/about-dialog.component.ts | 2 +-
src/app/posts.services.ts | 5 +++++
8 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8527313..54b21d0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -25,6 +25,23 @@ jobs:
cd backend
npm install
sudo npm install -g @angular/cli
+ - name: prepare localization
+ run: |
+ sudo npm install -g xliff-to-json
+ xliff-to-json ./src/assets/i18n
+ - name: Set hash
+ id: vars
+ run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
+ - name: Get current date
+ id: date
+ run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
+ - name: create-json
+ id: create-json
+ uses: jsdaniell/create-json@1.1.2
+ with:
+ name: "version.json"
+ json: '{"type": "autobuild", "tag": "N/A", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
+ dir: 'backend/'
- name: build
run: ng build --prod
- name: prepare artifact upload
diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml
index 96ec2c8..aae7fb3 100644
--- a/.github/workflows/docker-release.yml
+++ b/.github/workflows/docker-release.yml
@@ -13,6 +13,23 @@ jobs:
steps:
- name: checkout code
uses: actions/checkout@v2
+ - name: prepare localization
+ run: |
+ sudo npm install -g xliff-to-json
+ xliff-to-json ./src/assets/i18n
+ - name: Set hash
+ id: vars
+ run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
+ - name: Get current date
+ id: date
+ run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
+ - name: create-json
+ id: create-json
+ uses: jsdaniell/create-json@1.1.2
+ with:
+ name: "version.json"
+ json: '{"type": "docker", "tag": "latest", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
+ dir: 'backend/'
- name: setup platform emulator
uses: docker/setup-qemu-action@v1
- name: setup multi-arch docker build
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index c74f29b..9e0049b 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -10,6 +10,23 @@ jobs:
steps:
- name: checkout code
uses: actions/checkout@v2
+ - name: prepare localization
+ run: |
+ sudo npm install -g xliff-to-json
+ xliff-to-json ./src/assets/i18n
+ - name: Set hash
+ id: vars
+ run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
+ - name: Get current date
+ id: date
+ run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
+ - name: create-json
+ id: create-json
+ uses: jsdaniell/create-json@1.1.2
+ with:
+ name: "version.json"
+ json: '{"type": "docker", "tag": "nightly", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}'
+ dir: 'backend/'
- name: setup platform emulator
uses: docker/setup-qemu-action@v1
- name: setup multi-arch docker build
diff --git a/backend/app.js b/backend/app.js
index 7404f3c..33363d9 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -142,6 +142,14 @@ var validDownloadingAgents = [
const subscription_timeouts = {};
+let version_info = null;
+if (fs.existsSync('version.json')) {
+ version_info = fs.readJSONSync('version.json');
+ logger.verbose(`Version info: ${JSON.stringify(version_info, null, 2)}`);
+} else {
+ version_info = {'type': 'N/A', 'tag': 'N/A', 'commit': 'N/A', 'date': 'N/A'};
+}
+
// don't overwrite config if it already happened.. NOT
// let alreadyWritten = db.get('configWriteFlag').value();
let writeConfigMode = process.env.write_ytdl_config;
@@ -932,6 +940,10 @@ app.post('/api/setConfig', optionalJwt, function(req, res) {
}
});
+app.get('/api/versionInfo', (req, res) => {
+ res.send({version_info: version_info});
+});
+
app.post('/api/restartServer', optionalJwt, (req, res) => {
// delayed by a little bit so that the client gets a response
setTimeout(() => {restartServer()}, 100);
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index cadd7ca..6780813 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -118,6 +118,10 @@ export class AppComponent implements OnInit, AfterViewInit {
}
this.postsService.reloadCategories();
+
+ this.postsService.getVersionInfo().subscribe(res => {
+ this.postsService.version_info = res['version_info'];
+ });
}
// theme stuff
diff --git a/src/app/dialogs/about-dialog/about-dialog.component.html b/src/app/dialogs/about-dialog/about-dialog.component.html
index ddf28f0..c869b8d 100644
--- a/src/app/dialogs/about-dialog/about-dialog.component.html
+++ b/src/app/dialogs/about-dialog/about-dialog.component.html
@@ -21,6 +21,17 @@
done Update available - {{latestGithubRelease['tag_name']}}. You can update from the settings menu.
You are up to date.
+
+ Installation type: {{postsService.version_info.type}}
+
+
+ Docker tag: {{postsService.version_info.tag}}
+
+
+ Commit hash: {{postsService.version_info.commit}}
+
+ Build date: {{postsService.version_info.date}}
+
Found a bug or have a suggestion? Click here to create an issue!
diff --git a/src/app/dialogs/about-dialog/about-dialog.component.ts b/src/app/dialogs/about-dialog/about-dialog.component.ts
index fb8c1fa..826421a 100644
--- a/src/app/dialogs/about-dialog/about-dialog.component.ts
+++ b/src/app/dialogs/about-dialog/about-dialog.component.ts
@@ -19,7 +19,7 @@ export class AboutDialogComponent implements OnInit {
sidepanel_mode = this.postsService.sidepanel_mode;
card_size = this.postsService.card_size;
- constructor(private postsService: PostsService) { }
+ constructor(public postsService: PostsService) { }
ngOnInit(): void {
this.getLatestGithubRelease();
diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts
index c0c8b56..22faa70 100644
--- a/src/app/posts.services.ts
+++ b/src/app/posts.services.ts
@@ -60,6 +60,7 @@ export class PostsService implements CanActivate {
categories = null;
sidenav = null;
locale = isoLangs['en'];
+ version_info = null;
constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document,
public snackBar: MatSnackBar, private titleService: Title) {
@@ -453,6 +454,10 @@ export class PostsService implements CanActivate {
return this.http.post(this.path + 'clearFinishedDownloads', {}, this.httpOptions);
}
+ getVersionInfo() {
+ return this.http.get(this.path + 'versionInfo', this.httpOptions);
+ }
+
updateServer(tag) {
return this.http.post(this.path + 'updateServer', {tag: tag}, this.httpOptions);
}
From 8aa354ac245c7862ebac238b974e9d245ebc6cdb Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Tue, 21 Sep 2021 20:03:26 -0600
Subject: [PATCH 11/15] Fixed issue where navigating to a sub's video would
play all videos from the subscription
---
src/app/components/recent-videos/recent-videos.component.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/app/components/recent-videos/recent-videos.component.ts b/src/app/components/recent-videos/recent-videos.component.ts
index 251c41d..2645424 100644
--- a/src/app/components/recent-videos/recent-videos.component.ts
+++ b/src/app/components/recent-videos/recent-videos.component.ts
@@ -202,7 +202,7 @@ export class RecentVideosComponent implements OnInit {
} else {
// normal subscriptions
!new_tab ? this.router.navigate(['/player', {uid: file.uid,
- type: file.isAudio ? 'audio' : 'video', sub_id: sub.id}])
+ type: file.isAudio ? 'audio' : 'video'}])
: window.open(`/#/player;uid=${file.uid};type=${file.isAudio ? 'audio' : 'video'}`);
}
} else {
From 75fc09ed99a4ffd0ecc0333eb23232db43a90d43 Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Tue, 21 Sep 2021 23:51:07 -0600
Subject: [PATCH 12/15] Improved arg simulation -- now uses same method as the
actual download
Added checkbox for advanced custom args to either replace all args or append
---
backend/app.js | 25 +++++-
backend/downloader.js | 4 +-
src/app/main/main.component.css | 4 +-
src/app/main/main.component.html | 25 +++---
src/app/main/main.component.ts | 140 ++++++++++++-------------------
src/app/posts.services.ts | 16 +++-
6 files changed, 113 insertions(+), 101 deletions(-)
diff --git a/backend/app.js b/backend/app.js
index 33363d9..97a29df 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -987,8 +987,9 @@ app.post('/api/downloadFile', optionalJwt, async function(req, res) {
const url = req.body.url;
const type = req.body.type;
const user_uid = req.isAuthenticated() ? req.user.uid : null;
- var options = {
+ const options = {
customArgs: req.body.customArgs,
+ additionalArgs: req.body.additionalArgs,
customOutput: req.body.customOutput,
selectedHeight: req.body.selectedHeight,
customQualityConfiguration: req.body.customQualityConfiguration,
@@ -996,7 +997,7 @@ app.post('/api/downloadFile', optionalJwt, async function(req, res) {
youtubePassword: req.body.youtubePassword,
ui_uid: req.body.ui_uid,
cropFileSettings: req.body.cropFileSettings
- }
+ };
const download = await downloader_api.createDownload(url, type, options, user_uid);
@@ -1012,6 +1013,26 @@ app.post('/api/killAllDownloads', optionalJwt, async function(req, res) {
res.send(result_obj);
});
+app.post('/api/generateArgs', optionalJwt, async function(req, res) {
+ const url = req.body.url;
+ const type = req.body.type;
+ const user_uid = req.isAuthenticated() ? req.user.uid : null;
+ const options = {
+ customArgs: req.body.customArgs,
+ additionalArgs: req.body.additionalArgs,
+ customOutput: req.body.customOutput,
+ selectedHeight: req.body.selectedHeight,
+ customQualityConfiguration: req.body.customQualityConfiguration,
+ youtubeUsername: req.body.youtubeUsername,
+ youtubePassword: req.body.youtubePassword,
+ ui_uid: req.body.ui_uid,
+ cropFileSettings: req.body.cropFileSettings
+ };
+
+ const args = await downloader_api.generateArgs(url, type, options, user_uid, true);
+ res.send({args: args});
+});
+
// gets all download mp3s
app.get('/api/getMp3s', optionalJwt, async function(req, res) {
// TODO: simplify
diff --git a/backend/downloader.js b/backend/downloader.js
index 16aaaa8..1c428ea 100644
--- a/backend/downloader.js
+++ b/backend/downloader.js
@@ -369,7 +369,7 @@ async function downloadQueuedFile(download_uid) {
// helper functions
-exports.generateArgs = async (url, type, options, user_uid = null) => {
+exports.generateArgs = async (url, type, options, user_uid = null, simulated = false) => {
const audioFolderPath = config_api.getConfigItem('ytdl_audio_folder_path');
const videoFolderPath = config_api.getConfigItem('ytdl_video_folder_path');
@@ -510,7 +510,7 @@ exports.generateArgs = async (url, type, options, user_uid = null) => {
// filter out incompatible args
downloadConfig = filterArgs(downloadConfig, is_audio);
- logger.verbose(`youtube-dl args being used: ${downloadConfig.join(',')}`);
+ if (!simulated) logger.verbose(`youtube-dl args being used: ${downloadConfig.join(',')}`);
return downloadConfig;
}
diff --git a/src/app/main/main.component.css b/src/app/main/main.component.css
index e2325f2..5a712ae 100644
--- a/src/app/main/main.component.css
+++ b/src/app/main/main.component.css
@@ -129,7 +129,9 @@ mat-form-field.mat-form-field {
}
.edit-button {
- margin-left: 10px;
+ margin-left: 5px;
+ margin-top: -6px;
+ margin-bottom: -5px;
top: -5px;
}
diff --git a/src/app/main/main.component.html b/src/app/main/main.component.html
index 3bfdc23..cba6565 100644
--- a/src/app/main/main.component.html
+++ b/src/app/main/main.component.html
@@ -111,8 +111,13 @@
+
+
+ Replace args
+
+
-
+
No need to include URL, just everything after. Args are delimited using two commas like so: ,,
@@ -127,7 +132,7 @@
-
+
Documentation.
Path is relative to the config download path. Don't include extension.
@@ -140,13 +145,13 @@
Use authentication
-
-
+
+
-
-
+
+
@@ -155,13 +160,13 @@
Crop file
-
-
+
+
-
-
+
+
diff --git a/src/app/main/main.component.ts b/src/app/main/main.component.ts
index 996d819..37653ba 100644
--- a/src/app/main/main.component.ts
+++ b/src/app/main/main.component.ts
@@ -1,7 +1,7 @@
import { Component, OnInit, ElementRef, ViewChild, ViewChildren, QueryList } from '@angular/core';
import {PostsService} from '../posts.services';
import {FileCardComponent} from '../file-card/file-card.component';
-import { Observable } from 'rxjs';
+import { Observable, Subject } from 'rxjs';
import {FormControl, Validators} from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
@@ -9,7 +9,6 @@ import { saveAs } from 'file-saver';
import { YoutubeSearchService, Result } from '../youtube-search.service';
import { Router, ActivatedRoute } from '@angular/router';
import { Platform } from '@angular/cdk/platform';
-import { v4 as uuid } from 'uuid';
import { ArgModifierDialogComponent } from 'app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component';
import { RecentVideosComponent } from 'app/components/recent-videos/recent-videos.component';
@@ -50,6 +49,7 @@ export class MainComponent implements OnInit {
customArgsEnabled = false;
customArgs = null;
customOutputEnabled = false;
+ replaceArgs = false;
customOutput = null;
youtubeAuthEnabled = false;
youtubeUsername = null;
@@ -212,6 +212,7 @@ export class MainComponent implements OnInit {
error: false
};
+ argsChangedSubject: Subject = new Subject(false);
simulatedOutput = '';
constructor(public postsService: PostsService, private youtubeSearch: YoutubeSearchService, public snackBar: MatSnackBar,
@@ -224,8 +225,6 @@ export class MainComponent implements OnInit {
if (this.autoStartDownload) {
this.downloadClicked();
}
-
- setInterval(() => this.getSimulatedOutput(), 1000);
}
async loadConfig() {
@@ -261,6 +260,10 @@ export class MainComponent implements OnInit {
this.customOutputEnabled = localStorage.getItem('customOutputEnabled') === 'true';
}
+ if (localStorage.getItem('replaceArgs') !== null) {
+ this.replaceArgs = localStorage.getItem('replaceArgs') === 'true';
+ }
+
if (localStorage.getItem('youtubeAuthEnabled') !== null) {
this.youtubeAuthEnabled = localStorage.getItem('youtubeAuthEnabled') === 'true';
}
@@ -323,6 +326,12 @@ export class MainComponent implements OnInit {
this.autoStartDownload = true;
}
+ this.argsChangedSubject
+ .debounceTime(500)
+ .subscribe((should_simulate) => {
+ if (should_simulate) this.getSimulatedOutput();
+ });
+
this.setCols();
}
@@ -412,7 +421,8 @@ export class MainComponent implements OnInit {
this.urlError = false;
// get common args
- const customArgs = (this.customArgsEnabled ? this.customArgs : null);
+ const customArgs = (this.customArgsEnabled && this.replaceArgs ? this.customArgs : null);
+ const additionalArgs = (this.customArgsEnabled && !this.replaceArgs ? this.customArgs : null);
const customOutput = (this.customOutputEnabled ? this.customOutput : null);
const youtubeUsername = (this.youtubeAuthEnabled && this.youtubeUsername ? this.youtubeUsername : null);
const youtubePassword = (this.youtubeAuthEnabled && this.youtubePassword ? this.youtubePassword : null);
@@ -445,7 +455,7 @@ export class MainComponent implements OnInit {
this.downloadingfile = true;
this.postsService.downloadFile(this.url, type, (this.selectedQuality === '' ? null : this.selectedQuality),
- customQualityConfiguration, customArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => {
+ customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => {
this.current_download = res['download'];
this.downloads.push(res['download']);
this.download_uids.push(res['download']['uid']);
@@ -593,6 +603,7 @@ export class MainComponent implements OnInit {
if (str !== this.last_valid_url && this.allowQualitySelect) {
// get info
this.getURLInfo(str);
+ this.argsChangedSubject.next(true);
}
this.last_valid_url = str;
}
@@ -630,79 +641,44 @@ export class MainComponent implements OnInit {
}
}
- getSimulatedOutput() {
- const customArgsExists = this.customArgsEnabled && this.customArgs;
- const globalArgsExists = this.globalCustomArgs && this.globalCustomArgs !== '';
-
- let full_string_array: string[] = [];
- const base_string_array = ['youtube-dl', this.url];
-
- if (customArgsExists) {
- this.simulatedOutput = base_string_array.join(' ') + ' ' + this.customArgs.split(',,').join(' ');
- return this.simulatedOutput;
- }
-
- full_string_array.push(...base_string_array);
+ argChanged(): void {
+ this.argsChangedSubject.next(true);
+ }
- const base_path = this.audioOnly ? this.audioFolderPath : this.videoFolderPath;
- const ext = this.audioOnly ? '.mp3' : '.mp4';
- // gets output
- let output_string_array = ['-o', base_path + '%(title)s' + ext];
- if (this.customOutputEnabled && this.customOutput) {
- output_string_array = ['-o', base_path + this.customOutput + ext];
- }
- // before pushing output, should check if using an external downloader
- if (!this.useDefaultDownloadingAgent && this.customDownloadingAgent === 'aria2c') {
- full_string_array.push('--external-downloader', 'aria2c');
- }
- // pushes output
- full_string_array.push(...output_string_array);
+ getSimulatedOutput(): void {
+ // this function should be very similar to downloadFile()
+ const customArgs = (this.customArgsEnabled && this.replaceArgs ? this.customArgs : null);
+ const additionalArgs = (this.customArgsEnabled && !this.replaceArgs ? this.customArgs : null);
+ const customOutput = (this.customOutputEnabled ? this.customOutput : null);
+ const youtubeUsername = (this.youtubeAuthEnabled && this.youtubeUsername ? this.youtubeUsername : null);
+ const youtubePassword = (this.youtubeAuthEnabled && this.youtubePassword ? this.youtubePassword : null);
- // logic splits into audio and video modes
- if (this.audioOnly) {
- // adds base audio string
- const format_array = [];
- const audio_format = this.getSelectedAudioFormat();
- if (audio_format) {
- format_array.push('-f', audio_format);
- } else if (this.selectedQuality) {
- format_array.push('--audio-quality', this.selectedQuality['format_id']);
- }
+ const type = this.audioOnly ? 'audio' : 'video';
- // pushes formats
- full_string_array.splice(2, 0, ...format_array);
+ const customQualityConfiguration = type === 'audio' ? this.getSelectedAudioFormat() : this.getSelectedVideoFormat();
- const additional_params = ['-x', '--audio-format', 'mp3', '--write-info-json', '--print-json'];
+ let cropFileSettings = null;
- full_string_array.push(...additional_params);
- } else {
- // adds base video string
- let format_array = ['-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4'];
- const video_format = this.getSelectedVideoFormat();
- if (video_format) {
- format_array = ['-f', video_format];
- } else if (this.selectedQuality) {
- format_array = [`bestvideo[height=${this.selectedQuality['format_id']}]+bestaudio/best[height=${this.selectedQuality}]`];
+ if (this.cropFile) {
+ cropFileSettings = {
+ cropFileStart: this.cropFileStart,
+ cropFileEnd: this.cropFileEnd
}
-
- // pushes formats
- full_string_array.splice(2, 0, ...format_array);
-
- const additional_params = ['--write-info-json', '--print-json'];
-
- full_string_array.push(...additional_params);
- }
-
- if (this.use_youtubedl_archive) {
- full_string_array.push('--download-archive', 'archive.txt');
}
- if (globalArgsExists) {
- full_string_array = full_string_array.concat(this.globalCustomArgs.split(',,'));
- }
-
- this.simulatedOutput = full_string_array.join(' ');
- return this.simulatedOutput;
+ this.postsService.generateArgs(this.url, type, (this.selectedQuality === '' ? null : this.selectedQuality),
+ customQualityConfiguration, customArgs, additionalArgs, customOutput, youtubeUsername, youtubePassword, cropFileSettings).subscribe(res => {
+ const simulated_args = res['args'];
+ if (simulated_args) {
+ // hide password if needed
+ const passwordIndex = simulated_args.indexOf('--password');
+ console.log(passwordIndex);
+ if (passwordIndex !== -1 && passwordIndex !== simulated_args.length - 1) {
+ simulated_args[passwordIndex + 1] = simulated_args[passwordIndex + 1].replace(/./g, '*');
+ }
+ this.simulatedOutput = `youtube-dl ${this.url} ${simulated_args.join(' ')}`;
+ }
+ });
}
errorFormats(url) {
@@ -746,6 +722,7 @@ export class MainComponent implements OnInit {
videoModeChanged(new_val) {
this.selectedQuality = '';
localStorage.setItem('audioOnly', new_val.checked.toString());
+ this.argsChangedSubject.next(true);
}
autoplayChanged(new_val) {
@@ -754,29 +731,22 @@ export class MainComponent implements OnInit {
customArgsEnabledChanged(new_val) {
localStorage.setItem('customArgsEnabled', new_val.checked.toString());
- if (new_val.checked === true && this.customOutputEnabled) {
- this.customOutputEnabled = false;
- localStorage.setItem('customOutputEnabled', 'false');
+ this.argsChangedSubject.next(true);
+ }
- this.youtubeAuthEnabled = false;
- localStorage.setItem('youtubeAuthEnabled', 'false');
- }
+ replaceArgsChanged(new_val) {
+ localStorage.setItem('replaceArgs', new_val.checked.toString());
+ this.argsChangedSubject.next(true);
}
customOutputEnabledChanged(new_val) {
localStorage.setItem('customOutputEnabled', new_val.checked.toString());
- if (new_val.checked === true && this.customArgsEnabled) {
- this.customArgsEnabled = false;
- localStorage.setItem('customArgsEnabled', 'false');
- }
+ this.argsChangedSubject.next(true);
}
youtubeAuthEnabledChanged(new_val) {
localStorage.setItem('youtubeAuthEnabled', new_val.checked.toString());
- if (new_val.checked === true && this.customArgsEnabled) {
- this.customArgsEnabled = false;
- localStorage.setItem('customArgsEnabled', 'false');
- }
+ this.argsChangedSubject.next(true);
}
getAudioAndVideoFormats(formats) {
diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts
index 22faa70..bee6500 100644
--- a/src/app/posts.services.ts
+++ b/src/app/posts.services.ts
@@ -175,11 +175,25 @@ export class PostsService implements CanActivate {
}
// tslint:disable-next-line: max-line-length
- downloadFile(url: string, type: string, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings = null) {
+ downloadFile(url: string, type: string, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings = null) {
return this.http.post(this.path + 'downloadFile', {url: url,
selectedHeight: selectedQuality,
customQualityConfiguration: customQualityConfiguration,
customArgs: customArgs,
+ additionalArgs: additionalArgs,
+ customOutput: customOutput,
+ youtubeUsername: youtubeUsername,
+ youtubePassword: youtubePassword,
+ type: type,
+ cropFileSettings: cropFileSettings}, this.httpOptions);
+ }
+
+ generateArgs(url: string, type: string, selectedQuality: string, customQualityConfiguration: string, customArgs: string = null, additionalArgs: string = null, customOutput: string = null, youtubeUsername: string = null, youtubePassword: string = null, cropFileSettings = null) {
+ return this.http.post(this.path + 'generateArgs', {url: url,
+ selectedHeight: selectedQuality,
+ customQualityConfiguration: customQualityConfiguration,
+ customArgs: customArgs,
+ additionalArgs: additionalArgs,
customOutput: customOutput,
youtubeUsername: youtubeUsername,
youtubePassword: youtubePassword,
From ec7f04552f241518cb542e6ca2dc1a7be770f208 Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Tue, 21 Sep 2021 23:56:04 -0600
Subject: [PATCH 13/15] Fixed mangled Subject initialization in main component
---
src/app/main/main.component.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/app/main/main.component.ts b/src/app/main/main.component.ts
index 37653ba..00e1c61 100644
--- a/src/app/main/main.component.ts
+++ b/src/app/main/main.component.ts
@@ -212,7 +212,7 @@ export class MainComponent implements OnInit {
error: false
};
- argsChangedSubject: Subject = new Subject(false);
+ argsChangedSubject: Subject = new Subject();
simulatedOutput = '';
constructor(public postsService: PostsService, private youtubeSearch: YoutubeSearchService, public snackBar: MatSnackBar,
From 562eaa1b9b5c15ac2052eaf953d24b5e58156c5f Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Wed, 22 Sep 2021 19:27:25 -0600
Subject: [PATCH 14/15] Added support for generate NFO files for Kodi
Minor UI updates to settings
---
backend/appdata/default.json | 3 +-
backend/config.js | 3 +-
backend/consts.js | 5 ++
backend/db.js | 3 +-
backend/downloader.js | 20 +++++
backend/package-lock.json | 73 ++++++++++++++++
backend/package.json | 1 +
backend/test/sample.info.json | 1 +
backend/test/tests.js | 10 +++
backend/utils.js | 8 +-
src/app/settings/settings.component.html | 103 ++++++++++++-----------
src/app/settings/settings.component.ts | 26 +++++-
12 files changed, 197 insertions(+), 59 deletions(-)
create mode 100644 backend/test/sample.info.json
diff --git a/backend/appdata/default.json b/backend/appdata/default.json
index 04f76de..44f2f02 100644
--- a/backend/appdata/default.json
+++ b/backend/appdata/default.json
@@ -33,7 +33,8 @@
"use_twitch_API": false,
"twitch_API_key": "",
"twitch_auto_download_chat": false,
- "use_sponsorblock_API": false
+ "use_sponsorblock_API": false,
+ "generate_NFO_files": false
},
"Themes": {
"default_theme": "default",
diff --git a/backend/config.js b/backend/config.js
index e50c472..95e364c 100644
--- a/backend/config.js
+++ b/backend/config.js
@@ -208,7 +208,8 @@ const DEFAULT_CONFIG = {
"use_twitch_API": false,
"twitch_API_key": "",
"twitch_auto_download_chat": false,
- "use_sponsorblock_API": false
+ "use_sponsorblock_API": false,
+ "generate_NFO_files": false
},
"Themes": {
"default_theme": "default",
diff --git a/backend/consts.js b/backend/consts.js
index 1f25021..849fa4c 100644
--- a/backend/consts.js
+++ b/backend/consts.js
@@ -114,6 +114,11 @@ exports.CONFIG_ITEMS = {
'key': 'ytdl_use_sponsorblock_api',
'path': 'YoutubeDLMaterial.API.use_sponsorblock_API'
},
+ 'ytdl_generate_nfo_files': {
+ 'key': 'ytdl_generate_nfo_files',
+ 'path': 'YoutubeDLMaterial.API.generate_NFO_files'
+ },
+
// Themes
'ytdl_default_theme': {
diff --git a/backend/db.js b/backend/db.js
index a4c8080..18f9064 100644
--- a/backend/db.js
+++ b/backend/db.js
@@ -217,8 +217,7 @@ function generateFileObject(file_path, type) {
var title = jsonobj.title;
var url = jsonobj.webpage_url;
var uploader = jsonobj.uploader;
- var upload_date = jsonobj.upload_date;
- upload_date = upload_date ? `${upload_date.substring(0, 4)}-${upload_date.substring(4, 6)}-${upload_date.substring(6, 8)}` : 'N/A';
+ var upload_date = utils.formatDateString(jsonobj.upload_date);
var size = stats.size;
diff --git a/backend/downloader.js b/backend/downloader.js
index 1c428ea..86e6f5e 100644
--- a/backend/downloader.js
+++ b/backend/downloader.js
@@ -11,6 +11,7 @@ const youtubedl = require('youtube-dl');
const logger = require('./logger');
const config_api = require('./config');
const twitch_api = require('./twitch');
+const { create } = require('xmlbuilder2');
const categories_api = require('./categories');
const utils = require('./utils');
@@ -328,6 +329,10 @@ async function downloadQueuedFile(download_uid) {
if (!success) logger.error('Failed to apply ID3 tag to audio file ' + output_json['_filename']);
}
+ if (config_api.getConfigItem('ytdl_generate_nfo_files')) {
+ exports.generateNFOFile(output_json, `${filepath_no_extension}.nfo`);
+ }
+
if (options.cropFileSettings) {
await utils.cropFile(full_file_path, options.cropFileSettings.cropFileStart, options.cropFileSettings.cropFileEnd, ext);
}
@@ -603,4 +608,19 @@ async function checkDownloadPercent(download_uid) {
const percent_complete = (sum_size/resulting_file_size * 100).toFixed(2);
await db_api.updateRecord('download_queue', {uid: download_uid}, {percent_complete: percent_complete});
});
+}
+
+exports.generateNFOFile = (info, output_path) => {
+ const nfo_obj = {
+ episodedetails: {
+ title: info['fulltitle'],
+ episode: info['playlist_index'] ? info['playlist_index'] : undefined,
+ premiered: utils.formatDateString(info['upload_date']),
+ plot: `${info['uploader_url']}\n${info['description']}\n${info['playlist_title'] ? info['playlist_title'] : ''}`,
+ director: info['artist'] ? info['artist'] : info['uploader']
+ }
+ };
+ const doc = create(nfo_obj);
+ const xml = doc.end({ prettyPrint: true });
+ fs.writeFileSync(output_path, xml);
}
\ No newline at end of file
diff --git a/backend/package-lock.json b/backend/package-lock.json
index fbade26..7c691f8 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -4,6 +4,38 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "@oozcitak/dom": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz",
+ "integrity": "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==",
+ "requires": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/url": "1.0.4",
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/infra": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
+ "integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
+ "requires": {
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/url": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
+ "integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
+ "requires": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8"
+ }
+ },
+ "@oozcitak/util": {
+ "version": "8.3.8",
+ "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
+ "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ=="
+ },
"@sindresorhus/is": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
@@ -1117,6 +1149,11 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ },
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -3030,6 +3067,11 @@
"memory-pager": "^1.0.2"
}
},
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -3593,6 +3635,37 @@
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz",
"integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="
},
+ "xmlbuilder2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.0.2.tgz",
+ "integrity": "sha512-h4MUawGY21CTdhV4xm3DG9dgsqyhDkZvVJBx88beqX8wJs3VgyGQgAn5VreHuae6unTQxh115aMK5InCVmOIKw==",
+ "requires": {
+ "@oozcitak/dom": "1.15.10",
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8",
+ "@types/node": "*",
+ "js-yaml": "3.14.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "js-yaml": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
+ "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ }
+ }
+ },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/backend/package.json b/backend/package.json
index c857561..339e94a 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -66,6 +66,7 @@
"unzipper": "^0.10.10",
"uuidv4": "^6.0.6",
"winston": "^3.2.1",
+ "xmlbuilder2": "^3.0.2",
"youtube-dl": "^3.0.2"
}
}
diff --git a/backend/test/sample.info.json b/backend/test/sample.info.json
new file mode 100644
index 0000000..8d65c5b
--- /dev/null
+++ b/backend/test/sample.info.json
@@ -0,0 +1 @@
+{"fps": 25, "webpage_url_basename": "watch", "vbr": 3546.159, "age_limit": 0, "_filename": "video\\20091024 - Rick Astley - Never Gonna Give You Up (Official Music Video).mp4", "height": 1080, "description": "Rick Astley's official music video for \u201cNever Gonna Give You Up", "thumbnail": "https://i.ytimg.com/vi_webp/dQw4w9WgXcQ/maxresdefault.webp", "resolution": null, "webpage_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "average_rating": 4.894496, "ext": "mp4", "formats": [{"fps": null, "abr": 46.492, "height": null, "format_id": "249", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=249&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=audio%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=1232413&dur=212.061&lmt=1624945854503369&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5511222&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAOQPPrlgzOqNtORq4sWu11c9B7xu7oDsAw2tubKwfknwAiBqNjjMPHEVKlGNnOplfYZ_zuITnJ0PQAicXP1qyYRDWA%3D%3D&sig=AOq0QJ8wRgIhAOBiYeG7Pq0puYb5QjUVfMdTQStw09143tjience7YyJAiEAyK77-fXJ55w7RP2_ML9Gysg9ZrqhjcBzsolQIVHx6I4=", "format": "249 - audio only (tiny)", "filesize": 1232413, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": 48000, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "tiny", "acodec": "opus", "quality": 0, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "none", "tbr": 46.492, "width": null}, {"fps": null, "abr": 61.494, "height": null, "format_id": "250", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=250&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=audio%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=1630086&dur=212.061&lmt=1624945852595198&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5511222&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgGn2dRpsfP4xqu8rwvbRoH6SV9eCoQNr9KhOHIzWHcfwCIQCNXPD8U5zRz8nOD86M7E79GYNf9sR1QYI8Q0vRwh90zQ%3D%3D&sig=AOq0QJ8wRAIgMX4-9T8B0Rk8YxA7umuAzrb7Cf81aYG4PiV3uKTP4zQCIDw876bIcVsfWIO4Lx4qS7txMIkqDsnofhAfcIrAc9-T", "format": "250 - audio only (tiny)", "filesize": 1630086, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": 48000, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "tiny", "acodec": "opus", "quality": 0, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "none", "tbr": 61.494, "width": null}, {"fps": null, "abr": 129.51, "height": null, "format_id": "140", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=140&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=audio%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=3433514&dur=212.091&lmt=1628122153868652&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5532434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAIb6WyFCUS1IO9DY2BvkCDbeQpYU54NUMD8wHVUv-CgoAiBBk9HxGnh0qQAJqGRNFHGTtqiNhjBxPQCfHWqDOmzMbg%3D%3D&sig=AOq0QJ8wRAIgUstXqxWkdk_oRE6snyI1OaunA8jmDtA5gFsO__xRSWgCIDN6rrueyDicOohCGgyy-VOLBEHuwtjxpTpEdFrdzLtd", "format": "140 - audio only (tiny)", "filesize": 3433514, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": 44100, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "tiny", "acodec": "mp4a.40.2", "quality": 0, "container": "m4a_dash", "ext": "m4a", "protocol": "https", "vcodec": "none", "tbr": 129.51, "width": null}, {"fps": null, "abr": 129.689, "height": null, "format_id": "251", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=251&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=audio%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=3437753&dur=212.061&lmt=1624945852795821&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5511222&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhAO1WGRPqP3fz7DeczBl9uDNWvypP_xmoQapWlTCG66d9AiEAvZrhvA9jWZGnwCDEhntzc9utiYJZq-_PdXBpKlfUKAY%3D&sig=AOq0QJ8wRQIgPP7v5vRzBQVhBUFexSLhOsqNNfttu2TFH4qIctUxqAsCIQDixqdmBoxi72zvNSXdw-VyXAKd6mQfO_GmsvapdAutvA==", "format": "251 - audio only (tiny)", "filesize": 3437753, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": 48000, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "tiny", "acodec": "opus", "quality": 0, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "none", "tbr": 129.689, "width": null}, {"fps": 25, "format": "394 - 256x144 (144p)", "height": 144, "format_id": "394", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=394&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=1806317&dur=212.040&lmt=1624947805339431&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgMcmJsqnRfEbWlqbPt1EPKCpOF5UzkyaABbAi0SXEwHICIHVGwJ69zGvjLE7SfFLy7c-1L-psZ1M4cHbx0s_FlJEu&sig=AOq0QJ8wRQIgXnlbLnaTYCnHNGSv3NHchQ_uPCQKO-EuJ8le0QekHdsCIQDsHRE_83b11n_QLvDF0qhNgOtpfYgkhKU05RNt_DiwYg==", "vbr": 68.15, "filesize": 1806317, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "144p", "acodec": "none", "quality": 0, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.00M.08", "tbr": 68.15, "width": 256}, {"fps": 25, "format": "160 - 256x144 (144p)", "height": 144, "format_id": "160", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=160&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=1902470&dur=212.040&lmt=1628130952822277&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhANAbvnZihueHQl6DlS0KDCcmD612v91WicDPh0MMooE3AiEApFWRu4aPyDGym8F6QMLxc8yrVTWSSFBaUxjDWrx59FA%3D&sig=AOq0QJ8wRgIhAIKLvUYN8RN1LzNPHRN4Rb3fC0zDev9KlSdeCExTXPosAiEA_yY2AJ69va_G3eTdbkifrdePATiSrgb8PVDdMk-6hYw=", "vbr": 71.777, "filesize": 1902470, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "144p", "acodec": "none", "quality": 0, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.4d400c", "tbr": 71.777, "width": 256}, {"fps": 25, "format": "278 - 256x144 (144p)", "height": 144, "format_id": "278", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=278&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=2377337&dur=212.040&lmt=1628133100068252&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgYxpgVafit-zpha31Q8EtJBdHaBpRj1y65ew-cOr0644CIQD8SJ7dYuyflAm0T7T6ny03WB5jOjmHO87TDSwLeAPwZA%3D%3D&sig=AOq0QJ8wRQIgZP8HNivYFUpLZC2a5UHDX26raL9ekwrCP3fNwgST874CIQDuD4D2kg8lxP-4BC8J_x9cP8vGKfwD1w9HVad9TXIbjg==", "vbr": 89.693, "filesize": 2377337, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "144p", "acodec": "none", "quality": 0, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "vp9", "tbr": 89.693, "width": 256}, {"fps": 25, "format": "133 - 426x240 (240p)", "height": 240, "format_id": "133", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=133&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=3107257&dur=212.040&lmt=1628130952261127&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgNlYpzWhXOUhMEpm6bv_NUP8flw8_gbDOPuh_BpF1NWkCIA7dMuvigM6xlyoiJa8HxjDx-zeZODadHPUQ7DSxuy-u&sig=AOq0QJ8wRQIgfZ33AlJlf8H6DyxSVCHeZvA7i3QC9giEfW2FL6iXqTACIQCYEK8Rqbt9EgjKbGEks_iWoxXtm6TFLPM1vmx7722hrg==", "vbr": 117.232, "filesize": 3107257, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "240p", "acodec": "none", "quality": 1, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.4d4015", "tbr": 117.232, "width": 426}, {"fps": 25, "format": "395 - 426x240 (240p)", "height": 240, "format_id": "395", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=395&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=3563582&dur=212.040&lmt=1624947923168885&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhALb3kDbV5djjgibZrxg1kD6hfnxNHcgVWv0snt354vKHAiEA5UJIuEWmRqTsPtKGbHwcWducF6aUoEaFxKx1Tz5L008%3D&sig=AOq0QJ8wRQIgKib1QlEvGVYibzu3l1BDT63OFgt9Ttv4HCcqpCKebncCIQCGk-H3AdMNUzWU5I7015YbmU_X4g2Es44BBWCzLYUM6w==", "vbr": 134.449, "filesize": 3563582, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "240p", "acodec": "none", "quality": 1, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.00M.08", "tbr": 134.449, "width": 426}, {"fps": 25, "format": "242 - 426x240 (240p)", "height": 240, "format_id": "242", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=242&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=4215000&dur=212.040&lmt=1628133101514133&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhAPDAPJegoPAAF6kQgTebJ5-GdTQHu-dnudbQ9wUfaIWKAiEA4kNlwtfnb1zuhOb7OlIlBInYYdOTFyoI9mE7-yxxbxM%3D&sig=AOq0QJ8wRgIhALxu_H89hpmniExLrH6A073CxYUCJVhiVe0KFK3Skz7gAiEAlnZsUIv_GSPJYDafWKjskYOJkbRY2tTqSVZO3tHiVPg=", "vbr": 159.026, "filesize": 4215000, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "240p", "acodec": "none", "quality": 1, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "vp9", "tbr": 159.026, "width": 426}, {"fps": 25, "format": "134 - 640x360 (360p)", "height": 360, "format_id": "134", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=134&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=5820414&dur=212.040&lmt=1628130952382425&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAOtn2CoLBwcHCnbLpyhRugJMSvb5A3Mt7q0oc2GewlP5AiBSL9UpjE1pdqmlim_prX4T9hURk5K8YDHf24Gvlo29Sw%3D%3D&sig=AOq0QJ8wRAIgGt5L323eYDn6EDy6r2IYX0xGkzGzVMeH7NruficAzMECIGrivYII2PAGKL5Rv6lDc-l53z6PVid6W_8Jco5BYmFB", "vbr": 219.596, "filesize": 5820414, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "360p", "acodec": "none", "quality": 2, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.4d401e", "tbr": 219.596, "width": 640}, {"fps": 25, "format": "396 - 640x360 (360p)", "height": 360, "format_id": "396", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=396&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=6957752&dur=212.040&lmt=1624947999257981&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgHlGjZ2Fo06YkUp_59h9RpX89UUj7yF86OMbElBaaDRQCIBIJuyfWeNSKFP3s6BkXIk8Cy3F2mHRO3PRoR5CuacA3&sig=AOq0QJ8wRQIhANp7jIO5PM8sEwGd4-EmADAfLNsIw-mWhZDI0XAmQ666AiAfEAjcDgczL2TMBWQm9xobP6cbCrDVxfVxR_3IbYIYXg==", "vbr": 262.507, "filesize": 6957752, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "360p", "acodec": "none", "quality": 2, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.01M.08", "tbr": 262.507, "width": 640}, {"fps": 25, "format": "243 - 640x360 (360p)", "height": 360, "format_id": "243", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=243&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=7257207&dur=212.040&lmt=1628133101141872&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgdk8qX0zqkEIlabAum60ghDNmMy2W1zWAsnvKpoef1igCIQCWvArsFhNndiLBBq7UEdk2qX9FvYej4tCuDFknrNyyDA%3D%3D&sig=AOq0QJ8wRgIhAN3hiLrHN-nYrc4xRIFk0mcVYxqR5FNRhzcEz8DJyLAuAiEAiIsaYG5R6ZcaTuWfwV4qp3iJqAYPBLX0QkDgNbXhGl4=", "vbr": 273.805, "filesize": 7257207, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "360p", "acodec": "none", "quality": 2, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "vp9", "tbr": 273.805, "width": 640}, {"fps": 25, "format": "135 - 854x480 (480p)", "height": 480, "format_id": "135", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=135&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=8935471&dur=212.040&lmt=1628130953383927&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgGK75aA2fI4WwFkPZV42bMbNbkOG6OtuIXjuFNqezr4MCIGst4mxew5OX2AYcbwTj9f0e3PBAS8QGTYs3yDeVbNdT&sig=AOq0QJ8wRgIhALIazj23a4uqcFohSavkQCmmByUR_7DxHo6ohKjOc5yiAiEAoleQpPWYZ8tO0O7gZsT_H4aUuGh_p9F2oNjrx5eLKqQ=", "vbr": 337.123, "filesize": 8935471, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "480p", "acodec": "none", "quality": 3, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.4d401e", "tbr": 337.123, "width": 854}, {"fps": 25, "format": "244 - 854x480 (480p)", "height": 480, "format_id": "244", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=244&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=10532052&dur=212.040&lmt=1628133102160132&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhAJKhoFYw7Q-a6k4sgJZO69oCR8yu-_86cfVvZDVnlxcrAiEA6ghEBhCbESj7wH3LcFmHp4dNFEVI_H3dazQKTWPxMnk%3D&sig=AOq0QJ8wRgIhAN3WW-w6rLDTOWF4r6kqvmbOlsgkp0wgxnvHeMJOPa8oAiEA4s9L5_hPFQ9pjUD9VWVjJrYKTT5pzeFfXCD2Cd7tR6s=", "vbr": 397.36, "filesize": 10532052, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "480p", "acodec": "none", "quality": 3, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "vp9", "tbr": 397.36, "width": 854}, {"fps": 25, "format": "397 - 854x480 (480p)", "height": 480, "format_id": "397", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=397&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=11930795&dur=212.040&lmt=1624948131494790&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgcoFDjq9zIiJ_ofRzFyQjv_6wRL4EV6mbVDCkwBYN8t0CIFvyQbtU537nm7Iw9-t_e9Scxlcyt5SwbrhtWIiA4zt5&sig=AOq0QJ8wRgIhAPf62Xh3p8Sk1zf3iZTK1zaEoSJz6eft26JJ9VR8N2CPAiEAtZtW4sdAYDDmAqS524Qxy6ZD9BZgvdFZWkTyZwrbkyo=", "vbr": 450.133, "filesize": 11930795, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "480p", "acodec": "none", "quality": 3, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.04M.08", "tbr": 450.133, "width": 854}, {"fps": 25, "format": "136 - 1280x720 (720p)", "height": 720, "format_id": "136", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=136&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=17375531&dur=212.040&lmt=1628130952538181&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAN1ZFXb_ZOXOofsWiuyAlB_PEmFOXLMiMWlLzcrb33zgAiARNS1RT8FOIEst33KIGloOKR9Y6_fSg0o1s_cr8PrDTQ%3D%3D&sig=AOq0QJ8wRAIgeCl2ZWgWyfopoNoWUVV4Lijvm2aYyFZhH4KZsPLOWb8CICgDOyLogiCIwOIiNz4zamJTtkakt8VDaLhV__Z4b9An", "vbr": 655.556, "filesize": 17375531, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "720p", "acodec": "none", "quality": 4, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.4d401f", "tbr": 655.556, "width": 1280}, {"fps": 25, "format": "247 - 1280x720 (720p)", "height": 720, "format_id": "247", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=247&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fwebm&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=18530394&dur=212.040&lmt=1628133100666546&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhAIEWZfOAPFeUw2-xI2l_IvQ2XJG92s_5Yd77n9pgCvISAiByI9uxsyN5xk_PtxDSFF4UG1Q-7OpXrYr3i6jBz880JQ%3D%3D&sig=AOq0QJ8wRgIhAL3l9xAE1mvJmZ5wEGtRO-f_vhHCRtts8Cj-jD1ZpcUqAiEAsKbVkjHRYLtXGbmwUT1qe6medMxHmIYGsLrPTftbuYI=", "vbr": 699.128, "filesize": 18530394, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "720p", "acodec": "none", "quality": 4, "container": "webm_dash", "ext": "webm", "protocol": "https", "vcodec": "vp9", "tbr": 699.128, "width": 1280}, {"fps": 25, "format": "398 - 1280x720 (720p)", "height": 720, "format_id": "398", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=398&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=22755091&dur=212.040&lmt=1624947952304594&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRgIhAPYMgegprlBtjtqtXJkbsbAeeXS6XNWySYoxae2IvrLKAiEApXXh7mr2C8UMrfXNGaIB--m-4kkSy91IN3muC3Z4t18%3D&sig=AOq0QJ8wRgIhAPm3dPdmeLw7e6muiJwhSDKe1nlkHoQ1WkXcmz6ngRkVAiEAqShfUbwRICZ7TI3pggP-3rWlFlpExlV1ebinn5JLc4k=", "vbr": 858.52, "filesize": 22755091, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "720p", "acodec": "none", "quality": 4, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.05M.08", "tbr": 858.52, "width": 1280}, {"fps": 25, "format": "399 - 1920x1080 (1080p)", "height": 1080, "format_id": "399", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=399&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=41772768&dur=212.040&lmt=1624948154710174&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5531432&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRAIgcCja1-Lsriw-hfwc2KwX9G4VBYJ1a9p3OGBQYwa3pywCIFMEO6QGSXUQoQomqSYxqUu4HOZHqHnhVUFlaroP-l2h&sig=AOq0QJ8wRQIgIPISNyI_OU4-cpSkzZjvP6oF2w0izlJKe8DCwl9bH5QCIQDHydWqPWx7k9ctYkmtelvOV6Ao_hUwUzeJuMaaXqllkw==", "vbr": 1576.033, "filesize": 41772768, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "1080p", "acodec": "none", "quality": 5, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "av01.0.08M.08", "tbr": 1576.033, "width": 1920}, {"fps": 25, "format": "137 - 1920x1080 (1080p)", "height": 1080, "format_id": "137", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=137&aitags=133%2C134%2C135%2C136%2C137%2C160%2C242%2C243%2C244%2C247%2C278%2C394%2C395%2C396%2C397%2C398%2C399&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=flWNw8FESVeF__wRUpmII5wG&gir=yes&clen=93990963&dur=212.040&lmt=1628130818054956&mt=1631594013&fvip=4&keepalive=yes&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5535434&n=7iJIhDM_ktV3660j&sparams=expire%2Cei%2Cip%2Cid%2Caitags%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgfImvk-1wtFA9tIjgPP0B-zd95cwOlEHMhBvV3aE7zl0CIQCEf3d3oZfoThLk__WJL1AOe1URRgkj_SIcftgH8HG_jg%3D%3D&sig=AOq0QJ8wRgIhAJItHQu2MeVv3to1Z0luBDsircwDXjWzWeBmYRAKDW9rAiEA1iafsfDk5Yp-9zACBxgmxyL_pidNC3mqYV_TKjHcklY=", "vbr": 3546.159, "filesize": 93990963, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": null, "downloader_options": {"http_chunk_size": 10485760}, "format_note": "1080p", "acodec": "none", "quality": 5, "container": "mp4_dash", "ext": "mp4", "protocol": "https", "vcodec": "avc1.640028", "tbr": 3546.159, "width": 1920}, {"fps": 25, "format": "18 - 640x360 (360p)", "height": 360, "format_id": "18", "url": "https://r2---sn-j5caxvox-cvpe.googlevideo.com/videoplayback?expire=1631616016&ei=sCdAYdCGAZD7kgadtbT4AQ&ip=174.126.238.181&id=o-AB6FjTBkJE3OCIRR6E4MV93s_EQC6Wem5GQY3nsgnbhd&itag=18&source=youtube&requiressl=yes&mh=7c&mm=31%2C29&mn=sn-j5caxvox-cvpe%2Csn-nx5s7n76&ms=au%2Crdu&mv=m&mvi=2&pl=24&initcwndbps=1847500&vprv=1&mime=video%2Fmp4&ns=zMV9mnhHv3UnwW1w1ilGGmgG&gir=yes&clen=16724503&ratebypass=yes&dur=212.091&lmt=1624987724234745&mt=1631594013&fvip=4&fexp=24001373%2C24007246&beids=9466585&c=WEB&txp=5530322&n=EFswOlbBGAoK1nv1&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIhANvKM6JozEQa97eFLe2GBuj7K6UqHz8r0ilGwRnrl5OBAiAHdOlZ3a0nr2sKPzU2cfBNdSgdtRYyYem2sOJCFRRdkg%3D%3D&sig=AOq0QJ8wRQIhAO27Mc8XHMtx364tjalsNLXk8X5zzE11s4ovWD-0cVMwAiB4giGZbFxOvmRb0Eo1OTuExAAWvFfl_IB8vrJXPHMAsQ==", "filesize": 16724503, "http_headers": {"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.33 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-us,en;q=0.5"}, "asr": 44100, "format_note": "360p", "acodec": "mp4a.40.2", "quality": 2, "ext": "mp4", "protocol": "https", "vcodec": "avc1.42001E", "tbr": 630.842, "width": 640}], "id": "dQw4w9WgXcQ", "format_id": "137+251", "uploader": "Rick Astley", "channel_id": "UCuAXFkgsw1L7xaCfnd5JJOw", "acodec": "opus", "thumbnails": [{"height": 94, "resolution": "168x94", "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg?sqp=-oaymwEbCKgBEF5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLDd2KtelLHaNSXrI9_5K-NvTscKNw", "width": 168, "id": "0"}, {"height": 110, "resolution": "196x110", "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg?sqp=-oaymwEbCMQBEG5IVfKriqkDDggBFQAAiEIYAXABwAEG&rs=AOn4CLBUpEOOWUXWkNyijQuZ4UPzp2BE-w", "width": 196, "id": "1"}, {"height": 138, "resolution": "246x138", "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg?sqp=-oaymwEcCPYBEIoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLBCyhr8AqpJ1SxKVU6SyK5ODJ_IpA", "width": 246, "id": "2"}, {"height": 188, "resolution": "336x188", "url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg?sqp=-oaymwEcCNACELwBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLB_p0PncTtkrhaNDZtntrE3gKkoYw", "width": 336, "id": "3"}, {"height": 1080, "resolution": "1920x1080", "url": "https://i.ytimg.com/vi_webp/dQw4w9WgXcQ/maxresdefault.webp", "width": 1920, "id": "4"}], "extractor_key": "Youtube", "fulltitle": "Rick Astley - Never Gonna Give You Up (Official Music Video)", "categories": ["Music"], "view_count": 1046140382, "format": "137 - 1920x1080 (1080p)+251 - audio only (tiny)", "is_live": null, "upload_date": "20091024", "track": "Never Gonna Give You Up (7\" Mix)", "extractor": "youtube", "artist": "Rick Astley", "abr": 129.689, "creator": "Rick Astley", "channel": "Rick Astley", "title": "Rick Astley - Never Gonna Give You Up (Official Music Video)", "vcodec": "avc1.640028", "display_id": "dQw4w9WgXcQ", "width": 1920, "alt_title": "Never Gonna Give You Up (7\" Mix)", "channel_url": "https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw", "stretched_ratio": null, "uploader_id": "UCuAXFkgsw1L7xaCfnd5JJOw", "like_count": 11756010, "playlist": null, "tags": ["rick astley", "Never Gonna Give You Up", "nggyu", "never gonna give you up lyrics", "rick rolled", "the boys soundtrack", "the boys amazon prime", "Never gonna give you up the boys", "official", "Rick Roll", "music video", "Rick Astley album", "rick astley official", "together forever", "Whenever You Need Somebody", "rickrolled", "WRECK-IT RALPH 2", "Fortnite song", "Fortnite event", "Fortnite dance", "fortnite never gonna give you up", "rick astley never gonna give you up", "rick astley never gonna give you up lyrics"], "duration": 212, "uploader_url": "http://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw", "dislike_count": 318477, "playlist_index": null}
\ No newline at end of file
diff --git a/backend/test/tests.js b/backend/test/tests.js
index 99b79b2..c52fa13 100644
--- a/backend/test/tests.js
+++ b/backend/test/tests.js
@@ -339,4 +339,14 @@ describe('Downloader', function() {
const args = await downloader_api.generateArgs(url, 'video', sub_options, 'admin');
console.log(args);
});
+
+ it('Generate kodi NFO file', async function() {
+ const nfo_file_path = './test/sample.nfo';
+ if (fs.existsSync(nfo_file_path)) {
+ fs.unlinkSync(nfo_file_path);
+ }
+ const sample_json = fs.readJSONSync('./test/sample.info.json');
+ downloader_api.generateNFOFile(sample_json, nfo_file_path);
+ assert(fs.existsSync(nfo_file_path), true);
+ });
});
diff --git a/backend/utils.js b/backend/utils.js
index 9c07833..137274d 100644
--- a/backend/utils.js
+++ b/backend/utils.js
@@ -45,8 +45,7 @@ async function getDownloadedFilesByType(basePath, type, full_metadata = false) {
files.push(jsonobj);
continue;
}
- var upload_date = jsonobj.upload_date;
- upload_date = upload_date ? `${upload_date.substring(0, 4)}-${upload_date.substring(4, 6)}-${upload_date.substring(6, 8)}` : null;
+ var upload_date = formatDateString(jsonobj.upload_date);
var isaudio = type === 'audio';
var file_obj = new File(id, jsonobj.title, jsonobj.thumbnail, isaudio, jsonobj.duration, jsonobj.webpage_url, jsonobj.uploader,
@@ -295,6 +294,10 @@ function removeFileExtension(filename) {
return filename_parts.join('.');
}
+function formatDateString(date_string) {
+ return date_string ? `${date_string.substring(0, 4)}-${date_string.substring(4, 6)}-${date_string.substring(6, 8)}` : 'N/A';
+}
+
function createEdgeNGrams(str) {
if (str && str.length > 3) {
const minGram = 3
@@ -389,6 +392,7 @@ module.exports = {
getCurrentDownloader: getCurrentDownloader,
recFindByExt: recFindByExt,
removeFileExtension: removeFileExtension,
+ formatDateString: formatDateString,
cropFile: cropFile,
createEdgeNGrams: createEdgeNGrams,
wait: wait,
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
index e7e0223..74a57dd 100644
--- a/src/app/settings/settings.component.html
+++ b/src/app/settings/settings.component.html
@@ -1,12 +1,5 @@
Settings
-
-
-
-
-
+
@@ -272,9 +265,12 @@
Also known as a Client ID. Generating a key is easy!
-
+
Use SponsorBlock API
+
+ Generate NFO files
+
@@ -423,52 +419,59 @@
-
-
-
-
Allow user registration
+
+
+
+ Users
-
-
-
-
- Internal
-
-
- LDAP
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
+ Allow user registration
-
-
-
-
+
+
+
+
+ Internal
+
+
+ LDAP
+
+
+
+
+
-
-
-
+
+
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
index 483c4db..7d8b4d3 100644
--- a/src/app/settings/settings.component.ts
+++ b/src/app/settings/settings.component.ts
@@ -12,6 +12,7 @@ import { ConfirmDialogComponent } from 'app/dialogs/confirm-dialog/confirm-dialo
import { moveItemInArray, CdkDragDrop } from '@angular/cdk/drag-drop';
import { InputDialogComponent } from 'app/input-dialog/input-dialog.component';
import { EditCategoryDialogComponent } from 'app/dialogs/edit-category-dialog/edit-category-dialog.component';
+import { ActivatedRoute, Router } from '@angular/router';
@Component({
selector: 'app-settings',
@@ -38,17 +39,28 @@ export class SettingsComponent implements OnInit {
latestGithubRelease = null;
CURRENT_VERSION = CURRENT_VERSION
- get settingsAreTheSame() {
+ tabs = ['main', 'downloader', 'extra', 'database', 'advanced', 'users', 'logs'];
+ tabIndex = 0;
+
+ INDEX_TO_TAB = Object.assign({}, this.tabs);
+ TAB_TO_INDEX = {};
+
+ usersTabDisabledTooltip = $localize`You must enable multi-user mode to access this tab.`;
+
+ get settingsAreTheSame(): boolean {
this._settingsSame = this.settingsSame()
return this._settingsSame;
}
- set settingsAreTheSame(val) {
+ set settingsAreTheSame(val: boolean) {
this._settingsSame = val;
}
constructor(public postsService: PostsService, private snackBar: MatSnackBar, private sanitizer: DomSanitizer,
- private dialog: MatDialog) { }
+ private dialog: MatDialog, private router: Router, private route: ActivatedRoute) {
+ // invert index to tab
+ Object.keys(this.INDEX_TO_TAB).forEach(key => { this.TAB_TO_INDEX[this.INDEX_TO_TAB[key]] = key; });
+ }
ngOnInit() {
if (this.postsService.initialized) {
@@ -66,6 +78,9 @@ export class SettingsComponent implements OnInit {
this.generated_bookmarklet_code = this.sanitizer.bypassSecurityTrustUrl(this.generateBookmarkletCode());
this.getLatestGithubRelease();
+
+ const tab = this.route.snapshot.paramMap.get('tab');
+ this.tabIndex = tab && this.TAB_TO_INDEX[tab] ? this.TAB_TO_INDEX[tab] : 0;
}
getConfig() {
@@ -98,6 +113,11 @@ export class SettingsComponent implements OnInit {
this.new_config = JSON.parse(JSON.stringify(this.initial_config));
}
+ tabChanged(event) {
+ const index = event['index'];
+ this.router.navigate(['/settings', {tab: this.INDEX_TO_TAB[index]}]);
+ }
+
dropCategory(event: CdkDragDrop) {
moveItemInArray(this.postsService.categories, event.previousIndex, event.currentIndex);
this.postsService.updateCategories(this.postsService.categories).subscribe(res => {
From db53a12635572e67f84c8de6947567b309878a6c Mon Sep 17 00:00:00 2001
From: Isaac Abadi
Date: Wed, 22 Sep 2021 21:29:15 -0600
Subject: [PATCH 15/15] Added Korean translations and updated source
translations file
---
src/app/settings/settings.component.ts | 2 +-
src/assets/i18n/messages.en.xlf | 747 +++++--
src/assets/i18n/messages.ko.json | 261 +++
src/assets/i18n/messages.ko.xlf | 2634 ++++++++++++++++++++++++
4 files changed, 3452 insertions(+), 192 deletions(-)
create mode 100644 src/assets/i18n/messages.ko.json
create mode 100644 src/assets/i18n/messages.ko.xlf
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
index 7d8b4d3..c30d153 100644
--- a/src/app/settings/settings.component.ts
+++ b/src/app/settings/settings.component.ts
@@ -21,7 +21,7 @@ import { ActivatedRoute, Router } from '@angular/router';
})
export class SettingsComponent implements OnInit {
all_locales = isoLangs;
- supported_locales = ['en', 'es', 'de', 'fr', 'nl', 'pt', 'it', 'ca', 'cs', 'nb', 'ru', 'zh', 'id', 'en-GB'];
+ supported_locales = ['en', 'es', 'de', 'fr', 'nl', 'pt', 'it', 'ca', 'cs', 'nb', 'ru', 'zh', 'ko', 'id', 'en-GB'];
initialLocale = localStorage.getItem('locale');
initial_config = null;
diff --git a/src/assets/i18n/messages.en.xlf b/src/assets/i18n/messages.en.xlf
index 99e0f16..da1b3d7 100644
--- a/src/assets/i18n/messages.en.xlf
+++ b/src/assets/i18n/messages.en.xlf
@@ -26,22 +26,10 @@
src/app/settings/settings.component.html
- 75
+ 67
Dark mode toggle label
-
- Settings
-
- src/app/app.component.html
- 28
-
-
- src/app/settings/settings.component.html
- 1
-
- Settings menu label
-
Home
@@ -58,7 +46,7 @@
src/app/components/login/login.component.html
- 15
+ 34
src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
@@ -82,6 +70,25 @@
Navigation menu Downloads Page title
+
+ Settings
+
+ src/app/app.component.html
+ 49
+
+
+ src/app/settings/settings.component.html
+ 1
+
+ Settings menu label
+
+
+ Download for has been queued!
+
+ src/app/main/main.component.ts
+ 469
+
+
Only Audio
@@ -122,13 +129,13 @@
YT search View button for searched video
-
- Multi-download Mode
+
+ Autoplay
src/app/main/main.component.html
70,71
- Multi-download Mode checkbox
+ Autoplay checkbox
Cancel
@@ -154,11 +161,19 @@
Use custom args checkbox
+
+ Replace args
+
+ src/app/main/main.component.html
+ 116,117
+
+ Replace args
+
Custom args
src/app/main/main.component.html
- 115
+ 120
src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
@@ -174,7 +189,7 @@
No need to include URL, just everything after. Args are delimited using two commas like so: ,,
src/app/main/main.component.html
- 118,119
+ 123,124
Custom Args input hint
@@ -182,7 +197,7 @@
Use custom output
src/app/main/main.component.html
- 126,127
+ 131,132
Use custom output checkbox
@@ -190,7 +205,7 @@
Custom output
src/app/main/main.component.html
- 130
+ 135
Custom output placeholder
@@ -198,7 +213,7 @@
Documentation
src/app/main/main.component.html
- 132
+ 137
src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
@@ -214,7 +229,7 @@
src/app/settings/settings.component.html
- 125
+ 117
Youtube-dl output template documentation link
@@ -222,7 +237,7 @@
Path is relative to the config download path. Don't include extension.
src/app/main/main.component.html
- 133
+ 138
src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
@@ -242,26 +257,10 @@
Crop file
src/app/main/main.component.html
- 155,156
+ 160,161
Crop video checkbox
-
- Crop from (seconds)
-
- src/app/main/main.component.html
- 159
-
- Crop from placeholder
-
-
- Crop to (seconds)
-
- src/app/main/main.component.html
- 164
-
- Crop to placeholder
-
Simulated command:
@@ -274,7 +273,7 @@
Use authentication
src/app/main/main.component.html
- 140,141
+ 145,146
Use authentication checkbox
@@ -282,7 +281,7 @@
Username
src/app/main/main.component.html
- 144
+ 149
YT Username placeholder
@@ -290,7 +289,7 @@
Password
src/app/main/main.component.html
- 149
+ 154
src/app/dialogs/add-user-dialog/add-user-dialog.component.html
@@ -302,6 +301,22 @@
YT Password placeholder
+
+ Crop from (seconds)
+
+ src/app/main/main.component.html
+ 164
+
+ Crop from placeholder
+
+
+ Crop to (seconds)
+
+ src/app/main/main.component.html
+ 169
+
+ Crop to placeholder
+
Create a playlist
@@ -386,7 +401,7 @@
src/app/settings/settings.component.html
- 18
+ 10
Subscription URL input placeholder
@@ -492,6 +507,10 @@
src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
84
+
+ src/app/dialogs/confirm-dialog/confirm-dialog.component.html
+ 16
+
src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
66
@@ -500,6 +519,18 @@
src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
54
+
+ src/app/settings/settings.component.html
+ 490
+
+
+ src/app/components/downloads/downloads.component.html
+ 61
+
+
+ src/app/components/downloads/downloads.component.html
+ 61
+
src/app/components/modify-users/modify-users.component.html
61
@@ -586,7 +617,7 @@
src/app/dialogs/about-dialog/about-dialog.component.html
- 59
+ 70
src/app/dialogs/share-media-dialog/share-media-dialog.component.html
@@ -638,7 +669,7 @@
src/app/subscriptions/subscriptions.component.html
- 31
+ 34
src/app/subscription/subscription/subscription.component.html
@@ -802,7 +833,7 @@
src/app/components/login/login.component.html
- 35
+ 38
Register user button
@@ -854,7 +885,7 @@
src/app/settings/settings.component.html
- 464
+ 487
src/app/components/modify-users/modify-users.component.html
@@ -918,6 +949,38 @@
Files search placeholder
+
+ File type
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 52
+
+ File type
+
+
+ Both
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 54
+
+ Both
+
+
+ Video only
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 55
+
+ Video only
+
+
+ Audio only
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 56
+
+ Audio only
+
No videos found.
@@ -982,7 +1045,7 @@
src/app/components/unified-file-card/unified-file-card.component.html
- 37
+ 43
Playlist edit button
@@ -998,11 +1061,11 @@
src/app/components/unified-file-card/unified-file-card.component.html
- 33
+ 39
src/app/components/unified-file-card/unified-file-card.component.html
- 39
+ 45
Delete playlist
@@ -1038,7 +1101,7 @@
src/app/components/unified-file-card/unified-file-card.component.html
- 34
+ 40
Delete and blacklist video button
@@ -1046,7 +1109,7 @@
views
src/app/player/player.component.html
- 15
+ 16
View count label
@@ -1134,7 +1197,7 @@
Playlists
src/app/subscriptions/subscriptions.component.html
- 27
+ 30
Subscriptions playlists title
@@ -1150,7 +1213,7 @@
You have no channel subscriptions.
src/app/subscriptions/subscriptions.component.html
- 24
+ 27
No channel subscriptions text
@@ -1158,7 +1221,7 @@
Name not available. Playlist retrieval in progress.
src/app/subscriptions/subscriptions.component.html
- 33
+ 36
Subscription playlist not available text
@@ -1166,15 +1229,22 @@
You have no playlist subscriptions.
src/app/subscriptions/subscriptions.component.html
- 43
+ 46
No playlist subscriptions text
+
+ You must enable multi-user mode to access this tab.
+
+ src/app/settings/settings.component.ts
+ 48
+
+
Main
src/app/settings/settings.component.html
- 12
+ 4
Main settings label
@@ -1182,7 +1252,7 @@
Downloader
src/app/settings/settings.component.html
- 102
+ 94
Downloader settings label
@@ -1190,7 +1260,7 @@
Extra
src/app/settings/settings.component.html
- 185
+ 198
Extra settings label
@@ -1198,7 +1268,7 @@
Database
src/app/settings/settings.component.html
- 284
+ 303
Database settings label
@@ -1206,47 +1276,27 @@
Advanced
src/app/settings/settings.component.html
- 320
+ 339
Host settings label
-
- Users
-
- src/app/settings/settings.component.html
- 403
-
-
- src/app/settings/settings.component.html
- 403
-
- Users settings label
-
Logs
src/app/settings/settings.component.html
- 451
+ 476
src/app/settings/settings.component.html
- 451
+ 476
Logs settings label
-
- {VAR_SELECT, select, true {Close} false {Cancel} other {otha}}
-
- src/app/settings/settings.component.html
- 467
-
- Settings cancel and close button
-
URL this app will be accessed from, without the port.
src/app/settings/settings.component.html
- 19
+ 11
URL setting input hint
@@ -1254,7 +1304,7 @@
Port
src/app/settings/settings.component.html
- 24
+ 16
Port input placeholder
@@ -1262,7 +1312,7 @@
The desired port. Default is 17442.
src/app/settings/settings.component.html
- 25
+ 17
Port setting input hint
@@ -1270,7 +1320,7 @@
Multi-user mode
src/app/settings/settings.component.html
- 34
+ 26
Multi user mode setting
@@ -1278,7 +1328,7 @@
Users base path
src/app/settings/settings.component.html
- 38
+ 30
Users base path placeholder
@@ -1286,7 +1336,7 @@
Base path for users and their downloaded videos.
src/app/settings/settings.component.html
- 39
+ 31
Users base path hint
@@ -1294,7 +1344,7 @@
Allow subscriptions
src/app/settings/settings.component.html
- 48
+ 40
Allow subscriptions setting
@@ -1302,7 +1352,7 @@
Subscriptions base path
src/app/settings/settings.component.html
- 52
+ 44
Subscriptions base path input setting placeholder
@@ -1310,7 +1360,7 @@
Base path for videos from your subscribed channels and playlists. It is relative to YTDL-Material's root folder.
src/app/settings/settings.component.html
- 53
+ 45
Subscriptions base path setting input hint
@@ -1318,7 +1368,7 @@
Check interval
src/app/settings/settings.component.html
- 58
+ 50
Check interval input setting placeholder
@@ -1326,7 +1376,7 @@
Unit is seconds, only include numbers.
src/app/settings/settings.component.html
- 59
+ 51
Check interval setting input hint
@@ -1334,7 +1384,7 @@
Sometimes new videos are downloaded before being fully processed. This setting will mean new videos will be checked for a higher quality version the following day.
src/app/settings/settings.component.html
- 63
+ 55
Redownload fresh uploads tooltip
@@ -1342,7 +1392,7 @@
Redownload fresh uploads
src/app/settings/settings.component.html
- 63
+ 55
Redownload fresh uploads
@@ -1350,7 +1400,7 @@
Theme
src/app/settings/settings.component.html
- 72
+ 64
Theme select label
@@ -1358,7 +1408,7 @@
Default
src/app/settings/settings.component.html
- 74
+ 66
Default theme label
@@ -1366,7 +1416,7 @@
Allow theme change
src/app/settings/settings.component.html
- 80
+ 72
Allow theme change setting
@@ -1374,7 +1424,7 @@
Language
src/app/settings/settings.component.html
- 89
+ 81
Language select label
@@ -1382,7 +1432,7 @@
Audio folder path
src/app/settings/settings.component.html
- 109
+ 101
Audio folder path input placeholder
@@ -1390,7 +1440,7 @@
Path for audio only downloads. It is relative to YTDL-Material's root folder.
src/app/settings/settings.component.html
- 110
+ 102
Aduio path setting input hint
@@ -1398,7 +1448,7 @@
Video folder path
src/app/settings/settings.component.html
- 116
+ 108
Video folder path input placeholder
@@ -1406,7 +1456,7 @@
Path for video downloads. It is relative to YTDL-Material's root folder.
src/app/settings/settings.component.html
- 117
+ 109
Video path setting input hint
@@ -1414,7 +1464,7 @@
Default file output
src/app/settings/settings.component.html
- 123
+ 115
Default file output placeholder
@@ -1422,7 +1472,7 @@
Path is relative to the above download paths. Don't include extension.
src/app/settings/settings.component.html
- 126
+ 118
Custom Output input hint
@@ -1430,7 +1480,7 @@
Global custom args
src/app/settings/settings.component.html
- 133
+ 125
Custom args input placeholder
@@ -1438,7 +1488,7 @@
Global custom args for downloads on the home page. Args are delimited using two commas like so: ,,
src/app/settings/settings.component.html
- 134
+ 126
Custom args setting input hint
@@ -1446,7 +1496,7 @@
Categories
src/app/settings/settings.component.html
- 144
+ 136
Categories
@@ -1454,7 +1504,7 @@
With this setting enabled, if a single video matches a category, the entire playlist will receive that category.
src/app/settings/settings.component.html
- 158
+ 150
Allow playlist categorization setting tooltip
@@ -1462,7 +1512,7 @@
Allow playlist categorization
src/app/settings/settings.component.html
- 158
+ 150
Allow playlist categorization setting label
@@ -1470,7 +1520,7 @@
Use youtube-dl archive
src/app/settings/settings.component.html
- 166
+ 158
Use youtubedl archive setting
@@ -1478,7 +1528,7 @@
Include thumbnail
src/app/settings/settings.component.html
- 170
+ 162
Include thumbnail setting
@@ -1486,15 +1536,47 @@
Include metadata
src/app/settings/settings.component.html
- 174
+ 166
Include metadata setting
+
+ Max concurrent downloads
+
+ src/app/settings/settings.component.html
+ 175
+
+ Max concurrent downloads
+
+
+ Limits the amount of downloads that can be simultaneously downloaded. Use -1 for no limit.
+
+ src/app/settings/settings.component.html
+ 176
+
+ Max concurrent downloads input hint
+
+
+ Download rate limit
+
+ src/app/settings/settings.component.html
+ 181
+
+ Download rate limit input placeholder
+
+
+ Rate limits your downloads to the specified amount. Ex: 200K
+
+ src/app/settings/settings.component.html
+ 182
+
+ Download rate limit input hint
+
Kill all downloads
src/app/settings/settings.component.html
- 178
+ 191
Kill all downloads button
@@ -1502,7 +1584,7 @@
Top title
src/app/settings/settings.component.html
- 191
+ 204
Top title input placeholder
@@ -1510,7 +1592,7 @@
File manager enabled
src/app/settings/settings.component.html
- 196
+ 209
File manager enabled setting
@@ -1518,7 +1600,7 @@
Downloads manager enabled
src/app/settings/settings.component.html
- 199
+ 212
Downloads manager enabled setting
@@ -1526,7 +1608,7 @@
Allow quality select
src/app/settings/settings.component.html
- 202
+ 215
Allow quality seelct setting
@@ -1534,23 +1616,23 @@
Download only mode
src/app/settings/settings.component.html
- 205
+ 218
Download only mode setting
-
- Allow multi-download mode
+
+ Allow autoplay
src/app/settings/settings.component.html
- 208
+ 221
- Allow multi-download mode setting
+ Allow autoplay setting
Enable Public API
src/app/settings/settings.component.html
- 216
+ 229
Enable Public API key setting
@@ -1558,7 +1640,7 @@
Public API Key
src/app/settings/settings.component.html
- 221
+ 234
Public API Key setting placeholder
@@ -1566,7 +1648,7 @@
View documentation
src/app/settings/settings.component.html
- 222
+ 235
View API docs setting hint
@@ -1574,7 +1656,7 @@
This will delete your old API key!
src/app/settings/settings.component.html
- 226
+ 239
delete api key tooltip
@@ -1582,7 +1664,7 @@
Generate
src/app/settings/settings.component.html
- 226
+ 239
Generate key button
@@ -1590,7 +1672,7 @@
Use YouTube API
src/app/settings/settings.component.html
- 235
+ 248
Use YouTube API setting
@@ -1598,7 +1680,7 @@
Youtube API Key
src/app/settings/settings.component.html
- 239
+ 252
Youtube API Key setting placeholder
@@ -1606,11 +1688,11 @@
Generating a key is easy!
src/app/settings/settings.component.html
- 240
+ 253
src/app/settings/settings.component.html
- 252
+ 265
Youtube API Key setting hint
@@ -1618,7 +1700,7 @@
Use Twitch API
src/app/settings/settings.component.html
- 244
+ 257
Use Twitch API setting
@@ -1626,7 +1708,7 @@
Twitch API Key
src/app/settings/settings.component.html
- 251
+ 264
Twitch API Key setting placeholder
@@ -1634,15 +1716,47 @@
Also known as a Client ID.
src/app/settings/settings.component.html
- 252
+ 265
Twitch API Key setting hint AKA preamble
+
+ Enables a button to skip ads when viewing supported videos.
+
+ src/app/settings/settings.component.html
+ 269
+
+ SponsorBlock API tooltip
+
+
+ Use SponsorBlock API
+
+ src/app/settings/settings.component.html
+ 269
+
+ Use SponsorBlock API setting
+
+
+ Generates NFO files with every download, primarily used by Kodi.
+
+ src/app/settings/settings.component.html
+ 272
+
+ Generate NFO files tooltip
+
+
+ Generate NFO files
+
+ src/app/settings/settings.component.html
+ 272
+
+ Generate NFO files setting
+
Auto-download Twitch Chat
src/app/settings/settings.component.html
- 247
+ 260
Auto download Twitch Chat setting
@@ -1650,15 +1764,15 @@
Click here
src/app/settings/settings.component.html
- 262
+ 281
src/app/settings/settings.component.html
- 268
+ 287
src/app/dialogs/about-dialog/about-dialog.component.html
- 25
+ 36
Chrome ext click here
@@ -1666,7 +1780,7 @@
to download the official YoutubeDL-Material Chrome extension manually.
src/app/settings/settings.component.html
- 262
+ 281
Chrome click here suffix
@@ -1674,7 +1788,7 @@
You must manually load the extension and modify the extension's settings to set the frontend URL.
src/app/settings/settings.component.html
- 263
+ 282
Chrome setup suffix
@@ -1682,7 +1796,7 @@
to install the official YoutubeDL-Material Firefox extension right off the Firefox extensions page.
src/app/settings/settings.component.html
- 268
+ 287
Firefox click here suffix
@@ -1690,7 +1804,7 @@
Detailed setup instructions.
src/app/settings/settings.component.html
- 269
+ 288
Firefox setup prefix link
@@ -1698,7 +1812,7 @@
Not much is required other than changing the extension's settings to set the frontend URL.
src/app/settings/settings.component.html
- 269
+ 288
Firefox setup suffix
@@ -1706,7 +1820,7 @@
Drag the link below to your bookmarks, and you're good to go! Just navigate to the YouTube video you'd like to download, and click the bookmark.
src/app/settings/settings.component.html
- 274
+ 293
Bookmarklet instructions
@@ -1714,7 +1828,7 @@
Generate 'audio only' bookmarklet
src/app/settings/settings.component.html
- 275
+ 294
Generate audio only bookmarklet checkbox
@@ -1722,7 +1836,7 @@
Database location:
src/app/settings/settings.component.html
- 290
+ 309
Database location label
@@ -1730,7 +1844,7 @@
Records per table
src/app/settings/settings.component.html
- 291
+ 310
Records per table label
@@ -1738,7 +1852,7 @@
MongoDB Connection String
src/app/settings/settings.component.html
- 299
+ 318
MongoDB Connection String
@@ -1746,7 +1860,7 @@
Example:
src/app/settings/settings.component.html
- 300
+ 319
MongoDB Connection String setting hint AKA preamble
@@ -1754,7 +1868,7 @@
Test connection string
src/app/settings/settings.component.html
- 304
+ 323
Test connection string button
@@ -1762,7 +1876,7 @@
Transfer DB to
src/app/settings/settings.component.html
- 308
+ 327
Transfer DB button
@@ -1770,7 +1884,7 @@
Database information could not be retrieved. Check the server logs for more information.
src/app/settings/settings.component.html
- 312
+ 331
Database info not retrieved error message
@@ -1778,7 +1892,7 @@
Select a downloader
src/app/settings/settings.component.html
- 326
+ 345
Default downloader select label
@@ -1786,7 +1900,7 @@
Use default downloading agent
src/app/settings/settings.component.html
- 335
+ 354
Use default downloading agent setting
@@ -1794,7 +1908,7 @@
Select a download agent
src/app/settings/settings.component.html
- 339
+ 358
Custom downloader select label
@@ -1802,7 +1916,7 @@
Log Level
src/app/settings/settings.component.html
- 353
+ 372
Log Level label
@@ -1810,7 +1924,7 @@
Login expiration
src/app/settings/settings.component.html
- 365
+ 384
Login expiration select label
@@ -1818,7 +1932,7 @@
Allow advanced download
src/app/settings/settings.component.html
- 376
+ 395
Allow advanced downloading setting
@@ -1826,7 +1940,7 @@
Use Cookies
src/app/settings/settings.component.html
- 384
+ 403
Use cookies setting
@@ -1834,7 +1948,7 @@
Set Cookies
src/app/settings/settings.component.html
- 385
+ 404
Set cookies button
@@ -1842,15 +1956,23 @@
Restart server
src/app/settings/settings.component.html
- 397
+ 416
Restart server button
+
+ Users
+
+ src/app/settings/settings.component.html
+ 425
+
+ Users settings label
+
Allow user registration
src/app/settings/settings.component.html
- 407
+ 431
Allow registration setting
@@ -1858,7 +1980,7 @@
Auth method
src/app/settings/settings.component.html
- 411
+ 435
Auth method select
@@ -1866,7 +1988,7 @@
Internal
src/app/settings/settings.component.html
- 413
+ 437
Internal auth method
@@ -1874,7 +1996,7 @@
LDAP
src/app/settings/settings.component.html
- 416
+ 440
LDAP auth method
@@ -1882,7 +2004,7 @@
LDAP URL
src/app/settings/settings.component.html
- 423
+ 447
LDAP URL
@@ -1890,7 +2012,7 @@
Bind DN
src/app/settings/settings.component.html
- 428
+ 452
Bind DN
@@ -1898,7 +2020,7 @@
Bind Credentials
src/app/settings/settings.component.html
- 433
+ 457
Bind Credentials
@@ -1906,7 +2028,7 @@
Search Base
src/app/settings/settings.component.html
- 438
+ 462
Search Base
@@ -1914,7 +2036,7 @@
Search Filter
src/app/settings/settings.component.html
- 443
+ 467
Search Filter
@@ -1950,11 +2072,35 @@
Version label
+
+ Installation type:
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 25
+
+ Installation type
+
+
+ Commit hash:
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 31
+
+ Commit hash
+
+
+ Build date:
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 33
+
+ Build date
+
Found a bug or have a suggestion?
src/app/dialogs/about-dialog/about-dialog.component.html
- 25
+ 36
About bug prefix
@@ -1962,7 +2108,7 @@
to create an issue!
src/app/dialogs/about-dialog/about-dialog.component.html
- 25
+ 36
About bug suffix
@@ -1990,6 +2136,14 @@
Update through settings menu hint
+
+ Docker tag:
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 28
+
+ Docker tag
+
Select a version:
@@ -2046,35 +2200,230 @@
Share video dialog title
-
- Session ID:
+
+ Creating download
+
+ src/app/components/downloads/downloads.component.ts
+ 58
+
+
+
+ Getting info
+
+ src/app/components/downloads/downloads.component.ts
+ 59
+
+
+
+ Downloading file
+
+ src/app/components/downloads/downloads.component.ts
+ 60
+
+
+
+ Complete
+
+ src/app/components/downloads/downloads.component.ts
+ 61
+
+
+
+ Clear finished downloads
+
+ src/app/components/downloads/downloads.component.ts
+ 129
+
+
+
+ Would you like to clear your finished downloads?
+
+ src/app/components/downloads/downloads.component.ts
+ 130
+
+
+
+ Clear
+
+ src/app/components/downloads/downloads.component.ts
+ 131
+
+
+
+ Error for
+
+ src/app/components/downloads/downloads.component.ts
+ 238
+
+
+
+ Copy to clipboard
+
+ src/app/components/downloads/downloads.component.ts
+ 240
+
+
+
+ Close
+
+ src/app/components/downloads/downloads.component.ts
+ 241
+
+
+
+ Copied to clipboard!
+
+ src/app/components/downloads/downloads.component.ts
+ 249
+
+
+
+ Date
src/app/components/downloads/downloads.component.html
- 5
+ 7
- Session ID
+ Date
-
- Clear all downloads
+
+ Title
src/app/components/downloads/downloads.component.html
- 18
+ 13
- clear all downloads action button
+ Title
-
- (current)
+
+ Subscription
src/app/components/downloads/downloads.component.html
- 6
+ 23
+
+ Subscription
+
+
+ Stage
+
+ src/app/components/downloads/downloads.component.html
+ 36
+
+ Stage
+
+
+ Progress
+
+ src/app/components/downloads/downloads.component.html
+ 42
+
+ Progress
+
+
+ Actions
+
+ src/app/components/downloads/downloads.component.html
+ 55
- Current session
+ Actions
+
+
+ Clear
+
+ src/app/components/downloads/downloads.component.html
+ 68
+
+
+ src/app/components/downloads/downloads.component.html
+ 68
+
+ Clear
+
+
+ Pause
+
+ src/app/components/downloads/downloads.component.html
+ 59
+
+
+ src/app/components/downloads/downloads.component.html
+ 59
+
+ Pause
+
+
+ Resume
+
+ src/app/components/downloads/downloads.component.html
+ 60
+
+
+ src/app/components/downloads/downloads.component.html
+ 60
+
+ Resume
+
+
+ Watch content
+
+ src/app/components/downloads/downloads.component.html
+ 64
+
+
+ src/app/components/downloads/downloads.component.html
+ 64
+
+ Watch content
+
+
+ Show error
+
+ src/app/components/downloads/downloads.component.html
+ 65
+
+
+ src/app/components/downloads/downloads.component.html
+ 65
+
+ Show error
+
+
+ Restart
+
+ src/app/components/downloads/downloads.component.html
+ 66
+
+ Restart
+
+
+ Pause all downloads
+
+ src/app/components/downloads/downloads.component.html
+ 83
+
+ Pause all downloads
+
+
+ Resume all downloads
+
+ src/app/components/downloads/downloads.component.html
+ 84
+
+ Resume all downloads
+
+
+ Clear finished downloads
+
+ src/app/components/downloads/downloads.component.html
+ 85
+
+ Clear finished downloads
No downloads available!
src/app/components/downloads/downloads.component.html
- 25
+ 90
No downloads label
@@ -2322,11 +2671,19 @@
Go to subscription menu item
+
+ Add to playlist
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 26
+
+ Add to playlist menu item
+
Delete and redownload
src/app/components/unified-file-card/unified-file-card.component.html
- 28
+ 34
src/app/subscription/subscription-file-card/subscription-file-card.component.html
@@ -2338,7 +2695,7 @@
Delete forever
src/app/components/unified-file-card/unified-file-card.component.html
- 31
+ 37
src/app/subscription/subscription-file-card/subscription-file-card.component.html
@@ -2362,6 +2719,14 @@
See less
+
+ Skip ad
+
+ src/app/components/skip-ad-button/skip-ad-button.component.html
+ 1
+
+ Skip ad button
+
Length:
diff --git a/src/assets/i18n/messages.ko.json b/src/assets/i18n/messages.ko.json
new file mode 100644
index 0000000..1fea7ad
--- /dev/null
+++ b/src/assets/i18n/messages.ko.json
@@ -0,0 +1,261 @@
+{
+ "004b222ff9ef9dd4771b777950ca1d0e4cd4348a": "대하여",
+ "994363f08f9fbfa3b3994ff7b35c6904fdff18d8": "프로필",
+ "adb4562d2dbd3584370e44496969d58c511ecb63": "다크",
+ "121cc5391cd2a5115bc2b3160379ee5b36cd7716": "설정",
+ "92eee6be6de0b11c924e3ab27db30257159c0a7c": "홈",
+ "6765b4c916060f6bc42d9bb69e80377dbcb5e4e9": "로그인",
+ "357064ca9d9ac859eb618e28e8126fa32be049e2": "구독",
+ "822fab38216f64e8166d368b59fe756ca39d301b": "다운로드",
+ "4a9889d36910edc8323d7bab60858ab3da6d91df": "오디오만",
+ "6a21ba5fb0ac804a525bf9ab168038c3ee88e661": "다운로드",
+ "a38ae1082fec79ba1f379978337385a539a28e73": "품질",
+ "4be966a9dcfbc9b54dfcc604b831c0289f847fa4": "URL 이용",
+ "d3f02f845e62cebd75fde451ab8479d2a8ad784d": "보기",
+ "96a01fafe135afc58b0f8071a4ab00234495ce18": "복수 다운로드 모드",
+ "6a3777f913cf3f288664f0632b9f24794fdcc24e": "취소",
+ "322ed150e02666fe2259c5b4614eac7066f4ffa0": "고급",
+ "4e4c721129466be9c3862294dc40241b64045998": "사용자 지정 인수 이용",
+ "ad2f8ac8b7de7945b80c8e424484da94e597125f": "사용자 지정 인수",
+ "a6911c2157f1b775284bbe9654ce5eb30cf45d7f": "URL을 포함할 필요가 없습니다. 이후의 모든 항목만 포함하면 됩니다. 인수는 다음과 같은 두 개의 쉼표를 사용하여 구분됩니다. : ,,",
+ "3a92a3443c65a52f37ca7efb8f453b35dbefbf29": "사용자 지정 출력 사용",
+ "d9c02face477f2f9cdaae318ccee5f89856851fb": "사용자 지정 출력",
+ "fcfd4675b4c90f08d18d3abede9a9a4dff4cfdc7": "문서",
+ "19d1ae64d94d28a29b2c57ae8671aace906b5401": "경로는 설정된 다운로드 경로에 상대적입니다. 확장자는 포함하지 마세요.",
+ "4e1291cb1d579e7b7a1b802e6a8fd16ef7a557fa": "파일 자르기",
+ "44d007f6f8a2b19f12d85f9e49647b4ac02d7cbe": "자르기 시작지점 (초)",
+ "661206c3ab91fa81e9d8b40afb29f1866b78432f": "자르기 마무리지점 (초)",
+ "b7ffe7c6586d6f3f18a9246806a7c7d5538ab43e": "시뮬레이션된 명령:",
+ "8fad10737d3e3735a6699a4d89cbf6c20f6bb55f": "인증 사용",
+ "08c74dc9762957593b91f6eb5d65efdfc975bf48": "아이디",
+ "c32ef07f8803a223a83ed17024b38e8d82292407": "비밀번호",
+ "17f0ea5d2d7a262b0e875acc70475f102aee84e6": "재생목록 만들기",
+ "cff1428d10d59d14e45edec3c735a27b5482db59": "제목",
+ "f61c6867295f3b53d23557021f2f4e0aa1d0b8fc": "종류",
+ "f0baeb8b69d120073b6d60d34785889b0c3232c8": "오디오",
+ "2d1ea268a6a9f483dbc2cbfe19bf4256a57a6af4": "동영상",
+ "f47e2d56dd8a145b2e9599da9730c049d52962a2": "오디오 파일",
+ "a52dae09be10ca3a65da918533ced3d3f4992238": "동영상",
+ "a9806cf78ce00eb2613eeca11354a97e033377b8": "재생목록이나 채널 구독",
+ "801b98c6f02fe3b32f6afa3ee854c99ed83474e6": "URL",
+ "93efc99ae087fc116de708ecd3ace86ca237cf30": "재생목록이나 채널 URL",
+ "08f5d0ef937ae17feb1b04aff15ad88911e87baf": "사용자 지정 이름",
+ "ea30873bd3f0d5e4fb2378eec3f0a1db77634a28": "모든 업로드 된 파일 다운로드",
+ "d641b8fa5ac5e85114c733b1f7de6976bd091f70": "최고 화질",
+ "c76a955642714b8949ff3e4b4990864a2e2cac95": "오디오 전용 모드",
+ "408ca4911457e84a348cecf214f02c69289aa8f1": "스트리밍 전용 모드",
+ "f432e1a8d6adb12e612127978ce2e0ced933959c": "이것들은 일반적인 인수 뒤에 추가됩니다.",
+ "98b6ec9ec138186d663e64770267b67334353d63": "사용자 지정 파일 출력",
+ "d7b35c384aecd25a516200d6921836374613dfe7": "취소",
+ "d0336848b0c375a1c25ba369b3481ee383217a4f": "구독",
+ "28a678e9cabf86e44c32594c43fa0e890135c20f": "마지막으로 업로드된 동영상 다운로드",
+ "e78c0d60ac39787f62c9159646fe0b3c1ed55a1d": "종류:",
+ "c52db455cca9109ee47e1a612c3f4117c09eb71b": "URL:",
+ "ca3dbbc7f3e011bffe32a10a3ea45cc84f30ecf1": "아이디:",
+ "f4e529ae5ffd73001d1ff4bbdeeb0a72e342e5c8": "닫기",
+ "8efc77bf327659c0fec1f518cf48a98cdcd9dddf": "아카이브 내보내기",
+ "3042bd3ad8dffcfeca5fd1ae6159fd1047434e95": "구독 취소",
+ "303e45ffae995c9817e510e38cb969e6bb3adcbf": "(일시정지)",
+ "a44d86aa1e6c20ced07aca3a7c081d8db9ded1c6": "아카이브:",
+ "616e206cb4f25bd5885fc35925365e43cf5fb929": "제목:",
+ "c6eb45d085384903e53ab001a3513d1de6a1dbac": "업로더:",
+ "109c6f4a5e46efb933612ededfaf52a13178b7e0": "파일 크기:",
+ "bd630d8669b16e5f264ec4649d9b469fe03e5ff4": "경로:",
+ "a67e7d843cef735c79d5ef1c8ba4af3e758912bb": "업로드 날짜:",
+ "0cc1dec590ecd74bef71a865fb364779bc42a749": "카테고리:",
+ "d9e83ac17026e70ef6e9c0f3240a3b2450367f40": "Youtube-dl 인수 수정",
+ "7fc1946abe2b40f60059c6cd19975d677095fd19": "시뮬레이션된 새 인수",
+ "0b71824ae71972f236039bed43f8d2323e8fd570": "인수 추가",
+ "c8b0e59eb491f2ac7505f0fbab747062e6b32b23": "카테고리로 찾기",
+ "9eeb91caef5a50256dd87e1c4b7b3e8216479377": "인수 값 이용",
+ "7de2451ed3fb8d8b847979bd3f0c740b970f167b": "인수 추가",
+ "b2623aee44b70c9a4ba1fce16c8a593b0a4c7974": "수정",
+ "25d8ad5eba2ec24e68295a27d6a4bb9b49e3dacd": "인수 값",
+ "91ecce65f1d23f9419d1c953cd6b7bc7f91c110e": "업데이터",
+ "b7ff2e2b909c53abe088fe60b9f4b6ac7757247f": "사용자 등록",
+ "024886ca34a6f309e3e51c2ed849320592c3faaa": "아이디",
+ "cfc2f436ec2beffb042e7511a73c89c372e86a6c": "등록",
+ "ebadf946ae90f13ecd0c70f09edbc0f983af8a0f": "새 쿠키 업로드",
+ "a8b7b9c168fd936a75e500806a8c0d7755ef1198": "참고: 새로운 쿠키를 추가하면 이전 쿠키를 덮어씁니다. 또한 쿠키는 사용자 개인이 아닌 전체에 적용됩니다.",
+ "98a8a42e5efffe17ab786636ed0139b4c7032d0e": "드래그 앤 드롭",
+ "4f389e41e4592f7f9bb76abdd8af4afdfb13f4f1": "재생목록 수정",
+ "52c9a103b812f258bcddc3d90a6e3f46871d25fe": "저장",
+ "cba36d610ddba59b6dd6fbec77199eabf0ff2de3": "재생할 때 재생목록 섞기",
+ "5caadefa4143cf6766a621b0f54f91f373a1f164": "콘텐츠 추가",
+ "33026f57ea65cd9c8a5d917a08083f71a718933a": "기본 순서",
+ "29376982b1205d9d6ea3d289e8e2f8e1ac2839b1": "순서 거꾸로",
+ "d02888c485d3aeab6de628508f4a00312a722894": "내 동영상",
+ "7e892ba15f2c6c17e83510e273b3e10fc32ea016": "검색",
+ "73423607944a694ce6f9e55cfee329681bb4d9f9": "동영상 없음.",
+ "3697f8583ea42868aa269489ad366103d94aece7": "수정중",
+ "07db550ae114d9faad3a0cbb68bcc16ab6cd31fc": "일시정지됨",
+ "c3b0b86523f1d10e84a71f9b188d54913a11af3b": "카테고리 수정중",
+ "2489eefea00931942b91f4a1ae109514b591e2e1": "규칙",
+ "e4eeb9106dbcbc91ca1ac3fb4068915998a70f37": "새로운 규칙 추가",
+ "792dc6a57f28a1066db283f2e736484f066005fd": "트위치 채팅 다운로드",
+ "28f86ffd419b869711aa13f5e5ff54be6d70731c": "수정",
+ "826b25211922a1b46436589233cb6f1a163d89b7": "삭제",
+ "321e4419a943044e674beb55b8039f42a9761ca5": "정보",
+ "e684046d73bcee88e82f7ff01e2852789a05fc32": "동영상 수:",
+ "34504b488c24c27e68089be549f0eeae6ebaf30b": "삭제하고 블랙리스트 추가",
+ "dad95154dcef3509b8cc705046061fd24994bbb7": "조회수",
+ "4d8a18b04a1f785ecd8021ac824e0dfd5881dbfc": "성공적으로 다운로드 완료",
+ "348cc5d553b18e862eb1c1770e5636f6b05ba130": "에러 발생",
+ "4f8b2bb476981727ab34ed40fde1218361f92c45": "세부사항",
+ "e9aff8e6df2e2bf6299ea27bb2894c70bc48bd4d": "에러 발생:",
+ "77b0c73840665945b25bd128709aa64c8f017e1c": "다운로드 시작:",
+ "08ff9375ec078065bcdd7637b7ea65fce2979266": "다운로드 끝:",
+ "ad127117f9471612f47d01eae09709da444a36a4": "파일 경로(들):",
+ "e2319dec5b4ccfb6ed9f55ccabd63650a8fdf547": "구독중",
+ "807cf11e6ac1cde912496f764c176bdfdd6b7e19": "채널",
+ "47546e45bbb476baaaad38244db444c427ddc502": "재생목록",
+ "29b89f751593e1b347eef103891b7a1ff36ec03f": "이름이 유효하지 않음. 채널 검색중.",
+ "4636cd4a1379c50d471e98786098c4d39e1e82ad": "구독중인 채널이 없습니다.",
+ "2e0a410652cb07d069f576b61eab32586a18320d": "이름이 유효하지 않음. 플레이리스트 검색중.",
+ "587b57ced54965d8874c3fd0e9dfedb987e5df04": "구독중인 재생목록이 없습니다.",
+ "82421c3e46a0453a70c42900eab51d58d79e6599": "메인",
+ "0ba25ad86a240576c4f20a2fada4722ebba77b1e": "다운로더",
+ "d5f69691f9f05711633128b5a3db696783266b58": "추가",
+ "fb324ec7da611c6283caa6fc6257c39a56d6aaf7": "데이터베이스",
+ "bc2e854e111ecf2bd7db170da5e3c2ed08181d88": "고급",
+ "4d13a9cd5ed3dcee0eab22cb25198d43886942be": "사용자",
+ "eb3d5aefff38a814b76da74371cbf02c0789a1ef": "로그",
+ "fe8fd36dbf5deee1d56564965787a782a66eba44": "{VAR_SELECT, select, true {닫다} false {취소} other {기타}}",
+ "54c512cca1923ab72faf1a0bd98d3d172469629a": "포트를 제외한 이 앱에 접속할 URL.",
+ "cb2741a46e3560f6bc6dfd99d385e86b08b26d72": "포트",
+ "22e8f1d0423a3b784fe40fab187b92c06541b577": "포트 설정. 기본 포트는 17442 입니다.",
+ "d4477669a560750d2064051a510ef4d7679e2f3e": "복수 사용자 모드",
+ "2eb03565fcdce7a7a67abc277a936a32fcf51557": "사용자 기본 경로",
+ "a64505c41150663968e277ec9b3ddaa5f4838798": "사용자와 그들의 동영상 다운로드를 위한 기본 경로.",
+ "4e3120311801c4acd18de7146add2ee4a4417773": "구독 허용",
+ "4bee2a4bef2d26d37c9b353c278e24e5cd309ce3": "구독 기본 경로",
+ "bc9892814ee2d119ae94378c905ea440a249b84a": "구독된 채널과 재생목록에서 나온 영상들을 위한 기본 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.",
+ "5bef4b25ba680da7fff06b86a91b1fc7e6a926e3": "확인 간격",
+ "0f56a7449b77630c114615395bbda4cab398efd8": "단위는 초이며, 숫자만 넣으세요.",
+ "13759b09a7f4074ceee8fa2f968f9815fdf63295": "가끔 새 동영상이 최고 화질 처리 전에 다운로드 될 때가 있습니다. 이 설정은 새 동영상이 더 높은 화질의 버전이 있는지 다음 날짜에 확인됨을 의미합니다.",
+ "3d1a47dc18b7bd8b5d9e1eb44b235ed9c4a2b513": "높은 화질 재다운로드",
+ "27a56aad79d8b61269ed303f11664cc78bcc2522": "테마",
+ "ff7cee38a2259526c519f878e71b964f41db4348": "기본",
+ "7a6bacee4c31cb5c0ac2d24274fb4610d8858602": "테마 변경 허용",
+ "fe46ccaae902ce974e2441abe752399288298619": "언어",
+ "ab2756805742e84ad0cc0468f4be2d8aa9f855a5": "오디오 폴더 경로",
+ "c2c89cdf45d46ea64d2ed2f9ac15dfa4d77e26ca": "오디오 전용 다운로드 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.",
+ "46826331da1949bd6fb74624447057099c9d20cd": "동영상 폴더 경로",
+ "17c92e6d47a213fa95b5aa344b3f258147123f93": "동영상 다운로드 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.",
+ "cfe829634b1144bc44b6d38cf5584ea65db9804f": "기본 파일 출력",
+ "1148fd45287ff09955b938756bc302042bcb29c7": "경로는 위의 다운로드 경로에 상대적입니다. 확장자는 포함하지 마세요.",
+ "ef418d4ece7c844f3a5e431da1aa59bedd88da7b": "전반적으로 적용될 사용자 지정 인수",
+ "6b995e7130b4d667eaab6c5f61b362ace486d26d": "홈페이지에서의 다운로드에 대해 전반적으로 적용될 사용자 지정 인수. 인수는 다음과 같은 두 개의 쉼표를 사용하여 구분됩니다. : ,,",
+ "04201f9d27abd7d6f58a4328ab98063ce1072006": "카테고리",
+ "1f6d3986a970af27f16f8a95ce0dc3033cc90a83": "이 설정을 사용하면, 하나의 동영상이 카테고리와 일치할 경우, 전체 재생목록에 해당 카테고리가 표시됩니다.",
+ "5da94ccb2301f586af26916e921bdad6d673ab58": "재생목록 카테고리화 허용",
+ "78e49b7339b4fa7184dd21bcaae107ce9b7076f6": "Youtube-dl 아카이브 사용",
+ "ffc19f32b1cba0daefc0e5668f89346db1db83ad": "썸네일 포함",
+ "384de8f8f112c9e6092eb2698706d391553f3e8d": "메타데이터 포함",
+ "fb35145bfb84521e21b6385363d59221f436a573": "모든 다운로드 종료",
+ "61f8fd90b5f8cb20c70371feb2ee5e1fac5a9095": "상위 제목",
+ "78d3531417c0d4ba4c90f0d4ae741edc261ec8df": "파일 매니저 설정됨",
+ "a5a1be0a5df07de9eec57f5d2a86ed0204b2e75a": "다운로드 매니저 설정됨",
+ "c33bd5392b39dbed36b8e5a1145163a15d45835f": "화질 선택 허용",
+ "bda5508e24e0d77debb28bcd9194d8fefb1cfb92": "다운로드 전용 모드",
+ "09d31c803a7252658694e1e3176b97f5655a3fe3": "복수 다운로드 모드 허용",
+ "1c4dbce56d96b8974aac24a02f7ab2ee81415014": "오픈 API 허용",
+ "23bd81dcc30b74d06279a26d7a42e8901c1b124e": "오픈 API 키",
+ "41016a73d8ad85e6cb26dffa0a8fab9fe8f60d8e": "문서 보기",
+ "00a94f58d9eb2e3aa561440eabea616d0c937fa2": "이것은 예전 API키를 지울 것입니다!",
+ "1b258b258b4cc475ceb2871305b61756b0134f4a": "생성",
+ "d5d7c61349f3b0859336066e6d453fc35d334fe5": "유튜브 API 사용",
+ "ce10d31febb3d9d60c160750570310f303a22c22": "유튜브 API 키",
+ "8602e313cdfa7c4cc475ccbe86459fce3c3fd986": "키를 만드는 것은 쉽습니다!",
+ "d162f9fcd6a7187b391e004f072ab3da8377c47d": "트위치 API 사용",
+ "8ae23bc4302a479f687f4b20a84c276182e2519c": "트위치 API 키",
+ "84ffcebac2709ca0785f4a1d5ba274433b5beabc": "클라이언트 ID라고도 알려져 있음.",
+ "5fb1e0083c9b2a40ac8ae7dcb2618311c291b8b9": "트위치 채팅 자동 다운로드",
+ "9b3cedfa83c6d7acb3210953289d1be4aab115c7": "이곳을 누르세요",
+ "7f09776373995003161235c0c8d02b7f91dbc4df": "공식 YoutubeDL-Material 크롬 확장 프로그램을 수동으로 다운로드 하기 위해.",
+ "5b5296423906ab3371fdb2b5a5aaa83acaa2ee52": "반드시 확장 프로그램을 수동으로 실행하고 확장 프로그램 설정을 수정하여 프론트엔드 URL을 설정해야 합니다.",
+ "9a2ec6da48771128384887525bdcac992632c863": "파이어폭스 확장 프로그램 페이지에서 바로 공식 YoutubeDL-Material 파이어폭스 확장 프로그램을 설치하기 위해.",
+ "eb81be6b49e195e5307811d1d08a19259d411f37": "자세한 설정 지침.",
+ "cb17ff8fe3961cf90f44bee97c88a3f3347a7e55": "프론트엔드 URL을 설정하기 위해 확장 프로그램 설정을 변경하는 것 외에는 필요한 것이 많지 않습니다.",
+ "61b81b11aad0b9d970ece2fce18405f07eac69c2": "아래 링크를 북마크에 끌어다 놓으시면 됩니다! 이제 그냥 다운로드하고자 하는 유튜브 비디오 페이지에서 북마크를 클릭하면 됩니다.",
+ "c505d6c5de63cc700f0aaf8a4b31fae9e18024e5": "'오디오 전용' 북마크 생성",
+ "47955e2cc6986625528b4352034858180d675281": "데이터베이스 위치:",
+ "9f8de81d44ec2a9a58b97e589b9e3154b3966c60": "테이블당 레코드",
+ "3913164a51898aac444bf6c7150e46ad5a8a18ad": "몽고DB 연결 문자열",
+ "5473e36f5102e2ae22ce4c6620cacc40cc98da95": "예시:",
+ "d54142de169844b014ae913a4056c31495f4a305": "연결 문자열 테스트",
+ "98e94c9bdac1ca8beb29d73b2e6f7a9e5e035aec": "DB 전환",
+ "b1c08387975e6feada407c9b5f5f564261b8192b": "데이터베이스 정보를 검색할 수 없습니다. 자세한 내용은 서버 로그를 확인하세요.",
+ "ec71e08aee647ea4a71fd6b7510c54d84a797ca6": "다운로더 선택",
+ "5fab47f146b0a4b809dcebf3db9da94df6299ea1": "기본 다운로드 에이전트 사용",
+ "c776eb4992b6c98f58cd89b20c1ea8ac37888521": "다운로드 에이전트 선택",
+ "0c43af932e6a4ee85500e28f01b3538b4eb27bc4": "로그 레벨",
+ "db6c192032f4cab809aad35215f0aa4765761897": "로그인 만료",
+ "dc3d990391c944d1fbfc7cfb402f7b5e112fb3a8": "고급 다운로드 허용",
+ "431e5f3a0dde88768d1074baedd65266412b3f02": "쿠키 사용",
+ "80651a7ad1229ea6613557d3559f702cfa5aecf5": "쿠키 설정",
+ "635285fa5624d50a408feb7eb564c0db0d3f1ce1": "서버 재시작",
+ "37224420db54d4bc7696f157b779a7225f03ca9d": "사용자 등록 허용",
+ "fa548cee6ea11c160a416cac3e6bdec0363883dc": "인증 방법",
+ "4f56ced9d6b85aeb1d4346433361d47ea72dac1a": "내부",
+ "e3d7c5f019e79a3235a28ba24df24f11712c7627": "LDAP",
+ "1db9789b93069861019bd0ccaa5d4706b00afc61": "LDAP URL",
+ "f50fa6c09c8944aed504f6325f2913ee6c7a296a": "Bind DN",
+ "080cc6abcba236390fc22e79792d0d3443a3bd2a": "Bind Credentials",
+ "cfa67d14d84fe0e9fadf251dc51ffc181173b662": "기본 검색",
+ "e01d54ecc1a0fcf9525a3c100ed8b83d94e61c23": "검색 필터",
+ "cec82c0a545f37420d55a9b6c45c20546e82f94e": "YoutubeDL-Material에 대하여",
+ "199c17e5d6a419313af3c325f06dcbb9645ca618": "은(는) 구글의 Material 디자인 요건에 따라 만들어진 오픈소스 유튜브 다운로더 입니다. 당신은 당신이 좋아하는 동영상을 동영상이나 오디오 파일로 원활하게 받을 수 있으며, 심지어 당신이 좋아하는 채널이나 재생목록을 구독해 그들의 새로운 동영상을 지속적으로 업데이트 할 수도 있습니다.",
+ "bc0ad0ee6630acb7fcb7802ec79f5a0ee943c1a7": "은(는) 광범위한 API, 도커 지원, 현지화 (번역) 지원을 포함한 몇몇 엄청난 기능이 포함되어 있습니다! 아래 깃허브 아이콘을 클릭해 모든 지원되는 기능을 확인해보세요.",
+ "a45e3b05f0529dc5246d70ef62304c94426d4c81": "설치된 버전:",
+ "b33536f59b94ec935a16bd6869d836895dc5300c": "버그를 찾았거나 제안하실 사항이 있으신가요?",
+ "e1f398f38ff1534303d4bb80bd6cece245f24016": "이슈를 생성하기 위해!",
+ "e22f3a5351944f3a1a10cfc7da6f65dfbe0037fe": "업데이트 확인중...",
+ "a16e92385b4fd9677bb830a4b796b8b79c113290": "업데이트 가능",
+ "189b28aaa19b3c51c6111ad039c4fd5e2a22e370": "설정 메뉴에서 업데이트를 할 수 있습니다.",
+ "1372e61c5bd06100844bd43b98b016aabc468f62": "선택된 버전:",
+ "1f6d14a780a37a97899dc611881e6bc971268285": "공유 허용",
+ "6580b6a950d952df847cb3d8e7176720a740adc8": "타임스탬프 사용",
+ "4f2ed9e71a7c981db3e50ae2fedb28aff2ec4e6c": "초",
+ "3a6e5a6aa78ca864f6542410c5dafb6334538106": "클립보드에 복사",
+ "a249a5ae13e0835383885aaf697d2890cc3e53e9": "재생목록 공유",
+ "94e2674467c7a08a291f9bd97ce694d4e47ffd62": "파일 공유",
+ "a1ad8b1be9be43b5183bd2c3186d4e19496f2a0b": "세션 아이디:",
+ "b6c453e0e61faea184bbaf5c5b0a1e164f4de2a2": "모든 다운로드된 항목 지우기",
+ "eb98135e35af26a9a326ee69bd8ff104d36dd8ec": "(현재)",
+ "7117fc42f860e86d983bfccfcf2654e5750f3406": "다운로드된 항목 없음!",
+ "42ff677ec14f111e88bd6cdd30145378e994d1bf": "프로필",
+ "bb694b49d408265c91c62799c2b3a7e3151c824d": "로그아웃",
+ "ac9d09de42edca1296371e4d801349c9096ac8de": "UID:",
+ "a5ed099ffc9e96f6970df843289ade8a7d20ab9f": "생성됨:",
+ "fa96f2137af0a24e6d6d54c598c0af7d5d5ad344": "로그인하지 않았습니다.",
+ "a1dbca87b9f36d2b06a5cbcffb5814c4ae9b798a": "관리자 계정 생성",
+ "2d2adf3ca26a676bca2269295b7455a26fd26980": "기본 관리자 계정이 감지되지 않았습니다. 이것은 'admin'이라는 ID를 가진 관리자 계정을 만들고, 비밀번호를 설정할 것입니다.",
+ "70a67e04629f6d412db0a12d51820b480788d795": "생성",
+ "4d92a0395dd66778a931460118626c5794a3fc7a": "사용자 추가",
+ "b0d7dd8a1b0349622d6e0c6e643e24a9ea0efa1d": "역할 수정",
+ "746f64ddd9001ac456327cd9a3d5152203a4b93c": "ID",
+ "52c1447c1ec9570a2a3025c7e566557b8d19ed92": "역할",
+ "59a8c38db3091a63ac1cb9590188dc3a972acfb3": "액션",
+ "2bd201aea09e43fbfd3cd15ec0499b6755302329": "사용자 관리",
+ "95b95a9c79e4fd9ed41f6855e37b3b06af25bcab": "사용자 삭제",
+ "632e8b20c98e8eec4059a605a4b011bb476137af": "사용자 수정",
+ "29c97c8e76763bb15b6d515648fa5bd1eb0f7510": "사용자 UID:",
+ "e70e209561583f360b1e9cefd2cbb1fe434b6229": "새 비밀번호",
+ "6498fa1b8f563988f769654a75411bb8060134b9": "새 비밀번호 설정",
+ "544e09cdc99a8978f48521d45f62db0da6dcf742": "기본 역할 사용",
+ "4f20f2d5a6882190892e58b85f6ccbedfa737952": "네",
+ "3d3ae7deebc5949b0c1c78b9847886a94321d9fd": "아니오",
+ "57c6c05d8ebf4ef1180c2705033c044f655bb2c4": "역할 관리",
+ "5009630cdf32ab4f1c78737b9617b8773512c05a": "줄:",
+ "8a0bda4c47f10b2423ff183acefbf70d4ab52ea2": "로그 지우기",
+ "24dc3ecf7ec2c2144910c4f3d38343828be03a4c": "자동으로 생성됨",
+ "ccf5ea825526ac490974336cb5c24352886abc07": "파일 열기",
+ "5656a06f17c24b2d7eae9c221567b209743829a9": "새 탭에서 파일 열기",
+ "a0720c36ee1057e5c54a86591b722485c62d7b1a": "구독중으로 가기",
+ "94e01842dcee90531caa52e4147f70679bac87fe": "삭제하고 재다운로드",
+ "2031adb51e07a41844e8ba7704b054e98345c9c1": "영원히 삭제",
+ "ddc31f2885b1b33a7651963254b0c197f2a64086": "더 보기.",
+ "56a2a773fbd5a6b9ac2e6b89d29d70a2ed0f3227": "간략히 보기.",
+ "2054791b822475aeaea95c0119113de3200f5e1c": "길이:"
+}
\ No newline at end of file
diff --git a/src/assets/i18n/messages.ko.xlf b/src/assets/i18n/messages.ko.xlf
new file mode 100644
index 0000000..3746351
--- /dev/null
+++ b/src/assets/i18n/messages.ko.xlf
@@ -0,0 +1,2634 @@
+
+
+
+
+
+ About
+ 대하여
+
+ src/app/app.component.html
+ 32
+
+ About menu label
+
+
+ Profile
+ 프로필
+
+ src/app/app.component.html
+ 19
+
+ Profile menu label
+
+
+ Dark
+ 다크
+
+ src/app/app.component.html
+ 23
+
+
+ src/app/settings/settings.component.html
+ 75
+
+ Dark mode toggle label
+
+
+ Settings
+ 설정
+
+ src/app/app.component.html
+ 28
+
+
+ src/app/settings/settings.component.html
+ 1
+
+ Settings menu label
+
+
+ Home
+ 홈
+
+ src/app/app.component.html
+ 43
+
+ Navigation menu Home Page title
+
+
+ Login
+ 로그인
+
+ src/app/app.component.html
+ 44
+
+
+ src/app/components/login/login.component.html
+ 15
+
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 20
+
+ Navigation menu Login Page title
+
+
+ Subscriptions
+ 구독
+
+ src/app/app.component.html
+ 45
+
+ Navigation menu Subscriptions Page title
+
+
+ Downloads
+ 다운로드
+
+ src/app/app.component.html
+ 46
+
+ Navigation menu Downloads Page title
+
+
+ Only Audio
+ 오디오만
+
+ src/app/main/main.component.html
+ 65,66
+
+ Only Audio checkbox
+
+
+ Download
+ 다운로드
+
+ src/app/main/main.component.html
+ 79,80
+
+ Main download button
+
+
+ Quality
+ 품질
+
+ src/app/main/main.component.html
+ 19,20
+
+ Quality select label
+
+
+ Use URL
+ URL 이용
+
+ src/app/main/main.component.html
+ 51
+
+ YT search Use URL button for searched video
+
+
+ View
+ 보기
+
+ src/app/main/main.component.html
+ 55,56
+
+ YT search View button for searched video
+
+
+ Multi-download Mode
+ 복수 다운로드 모드
+
+ src/app/main/main.component.html
+ 70,71
+
+ Multi-download Mode checkbox
+
+
+ Cancel
+ 취소
+
+ src/app/main/main.component.html
+ 84,85
+
+ Cancel download button
+
+
+ Advanced
+ 고급
+
+ src/app/main/main.component.html
+ 96,97
+
+ Advanced download mode panel
+
+
+ Use custom args
+ 사용자 지정 인수 이용
+
+ src/app/main/main.component.html
+ 110,111
+
+ Use custom args checkbox
+
+
+ Custom args
+ 사용자 지정 인수
+
+ src/app/main/main.component.html
+ 115
+
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 57
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 44
+
+ Custom args placeholder
+
+
+ No need to include URL, just everything after. Args are delimited using two commas like so: ,,
+ URL을 포함할 필요가 없습니다. 이후의 모든 항목만 포함하면 됩니다. 인수는 다음과 같은 두 개의 쉼표를 사용하여 구분됩니다. : ,,
+
+ src/app/main/main.component.html
+ 118,119
+
+ Custom Args input hint
+
+
+ Use custom output
+ 사용자 지정 출력 사용
+
+ src/app/main/main.component.html
+ 126,127
+
+ Use custom output checkbox
+
+
+ Custom output
+ 사용자 지정 출력
+
+ src/app/main/main.component.html
+ 130
+
+ Custom output placeholder
+
+
+ Documentation
+ 문서
+
+ src/app/main/main.component.html
+ 132
+
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 69
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 56
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 47
+
+
+ src/app/settings/settings.component.html
+ 125
+
+ Youtube-dl output template documentation link
+
+
+ Path is relative to the config download path. Don't include extension.
+ 경로는 설정된 다운로드 경로에 상대적입니다. 확장자는 포함하지 마세요.
+
+ src/app/main/main.component.html
+ 133
+
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 70
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 57
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 48
+
+ Custom Output input hint
+
+
+ Crop file
+ 파일 자르기
+
+ src/app/main/main.component.html
+ 155,156
+
+ Crop video checkbox
+
+
+ Crop from (seconds)
+ 자르기 시작지점 (초)
+
+ src/app/main/main.component.html
+ 159
+
+ Crop from placeholder
+
+
+ Crop to (seconds)
+ 자르기 마무리지점 (초)
+
+ src/app/main/main.component.html
+ 164
+
+ Crop to placeholder
+
+
+ Simulated command:
+ 시뮬레이션된 명령:
+
+ src/app/main/main.component.html
+ 102,103
+
+ Simulated command label
+
+
+ Use authentication
+ 인증 사용
+
+ src/app/main/main.component.html
+ 140,141
+
+ Use authentication checkbox
+
+
+ Username
+ 아이디
+
+ src/app/main/main.component.html
+ 144
+
+ YT Username placeholder
+
+
+ Password
+ 비밀번호
+
+ src/app/main/main.component.html
+ 149
+
+
+ src/app/dialogs/add-user-dialog/add-user-dialog.component.html
+ 11
+
+
+ src/app/dialogs/set-default-admin-dialog/set-default-admin-dialog.component.html
+ 10
+
+ YT Password placeholder
+
+
+ Create a playlist
+ 재생목록 만들기
+
+ src/app/create-playlist/create-playlist.component.html
+ 1
+
+ Create a playlist dialog title
+
+
+ Name
+ 제목
+
+ src/app/create-playlist/create-playlist.component.html
+ 6
+
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 8
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 5
+
+ Playlist name placeholder
+
+
+ Type
+ 종류
+
+ src/app/create-playlist/create-playlist.component.html
+ 11
+
+ Type select
+
+
+ Audio
+ 오디오
+
+ src/app/create-playlist/create-playlist.component.html
+ 12
+
+ Audio
+
+
+ Video
+ 동영상
+
+ src/app/create-playlist/create-playlist.component.html
+ 13
+
+ Video
+
+
+ Audio files
+ 오디오 파일
+
+ src/app/create-playlist/create-playlist.component.html
+ 19
+
+ Audio files title
+
+
+ Videos
+ 동영상
+
+ src/app/create-playlist/create-playlist.component.html
+ 20
+
+
+ src/app/subscription/subscription/subscription.component.html
+ 29
+
+ Videos title
+
+
+ Subscribe to playlist or channel
+ 재생목록이나 채널 구독
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 1
+
+ Subscribe dialog title
+
+
+ URL
+ URL
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 8
+
+
+ src/app/settings/settings.component.html
+ 18
+
+ Subscription URL input placeholder
+
+
+ The playlist or channel URL
+ 재생목록이나 채널 URL
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 9
+
+ Subscription URL input hint
+
+
+ Custom name
+ 사용자 지정 이름
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 19
+
+ Subscription custom name placeholder
+
+
+ Download all uploads
+ 모든 업로드 된 파일 다운로드
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 23
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 10
+
+ Download all uploads subscription setting
+
+
+ Max quality
+ 최고 화질
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 40
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 32
+
+ Max quality placeholder
+
+
+ Audio-only mode
+ 오디오 전용 모드
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 47
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 27
+
+ Streaming-only mode
+
+
+ Streaming-only mode
+ 스트리밍 전용 모드
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 52
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 39
+
+ Streaming-only mode
+
+
+ These are added after the standard args.
+ 이것들은 일반적인 인수 뒤에 추가됩니다.
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 60
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 47
+
+ Custom args hint
+
+
+ Custom file output
+ 사용자 지정 파일 출력
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 66
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 53
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 44
+
+ Subscription custom file output placeholder
+
+
+ Cancel
+ 취소
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 79
+
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 84
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 66
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 54
+
+
+ src/app/components/modify-users/modify-users.component.html
+ 61
+
+ Subscribe cancel button
+
+
+ Subscribe
+ 구독
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 81
+
+ Subscribe button
+
+
+ Download videos uploaded in the last
+ 마지막으로 업로드된 동영상 다운로드
+
+ src/app/dialogs/subscribe-dialog/subscribe-dialog.component.html
+ 26
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 13
+
+ Download time range prefix
+
+
+ Type:
+ 종류:
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 5
+
+ Subscription type property
+
+
+ URL:
+ URL:
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 9
+
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 9
+
+ Subscription URL property
+
+
+ ID:
+ 아이디:
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 13
+
+
+ src/app/file-card/file-card.component.html
+ 7
+
+
+ src/app/download-item/download-item.component.html
+ 4
+
+ Subscription ID property
+
+
+ Close
+ 닫기
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 23
+
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 35
+
+
+ src/app/dialogs/update-progress-dialog/update-progress-dialog.component.html
+ 17
+
+
+ src/app/dialogs/add-user-dialog/add-user-dialog.component.html
+ 18
+
+
+ src/app/dialogs/cookies-uploader-dialog/cookies-uploader-dialog.component.html
+ 40
+
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 59
+
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 29
+
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 27
+
+
+ src/app/components/manage-user/manage-user.component.html
+ 30
+
+
+ src/app/components/manage-role/manage-role.component.html
+ 18
+
+ Close subscription info button
+
+
+ Export Archive
+ 아카이브 내보내기
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 24
+
+ Export Archive button
+
+
+ Unsubscribe
+ 구독 취소
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 26
+
+ Unsubscribe button
+
+
+ (Paused)
+ (일시정지)
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 1
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 1
+
+
+ src/app/subscriptions/subscriptions.component.html
+ 12
+
+
+ src/app/subscriptions/subscriptions.component.html
+ 31
+
+
+ src/app/subscription/subscription/subscription.component.html
+ 5
+
+ Paused suffix
+
+
+ Archive:
+ 아카이브:
+
+ src/app/dialogs/subscription-info-dialog/subscription-info-dialog.component.html
+ 17
+
+ Subscription ID property
+
+
+ Name:
+ 제목:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 5
+
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 6
+
+ Video name property
+
+
+ Uploader:
+ 업로더:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 13
+
+ Video ID property
+
+
+ File size:
+ 파일 크기:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 17
+
+ Video file size property
+
+
+ Path:
+ 경로:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 21
+
+ Video path property
+
+
+ Upload Date:
+ 업로드 날짜:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 25
+
+ Video upload date property
+
+
+ Category:
+ 카테고리:
+
+ src/app/dialogs/video-info-dialog/video-info-dialog.component.html
+ 29
+
+ Category property
+
+
+ Modify youtube-dl args
+ Youtube-dl 인수 수정
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 1
+
+ Modify args title
+
+
+ Simulated new args
+ 시뮬레이션된 새 인수
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 8
+
+ Simulated args title
+
+
+ Add an arg
+ 인수 추가
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 34
+
+ Add arg card title
+
+
+ Search by category
+ 카테고리로 찾기
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 60
+
+ Search args by category button
+
+
+ Use arg value
+ 인수 값 이용
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 64
+
+ Use arg value checkbox
+
+
+ Add arg
+ 인수 추가
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 73
+
+ Search args by category button
+
+
+ Modify
+ 수정
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 85
+
+ Arg modifier modify button
+
+
+ Arg value
+ 인수 값
+
+ src/app/dialogs/arg-modifier-dialog/arg-modifier-dialog.component.html
+ 68
+
+ Arg value placeholder
+
+
+ Updater
+ 업데이터
+
+ src/app/dialogs/update-progress-dialog/update-progress-dialog.component.html
+ 1
+
+ Update progress dialog title
+
+
+ Register a user
+ 사용자 등록
+
+ src/app/dialogs/add-user-dialog/add-user-dialog.component.html
+ 1
+
+ Register user dialog title
+
+
+ User name
+ 아이디
+
+ src/app/dialogs/add-user-dialog/add-user-dialog.component.html
+ 6
+
+ User name placeholder
+
+
+ Register
+ 등록
+
+ src/app/dialogs/add-user-dialog/add-user-dialog.component.html
+ 17
+
+
+ src/app/components/login/login.component.html
+ 35
+
+ Register user button
+
+
+ Upload new cookies
+ 새 쿠키 업로드
+
+ src/app/dialogs/cookies-uploader-dialog/cookies-uploader-dialog.component.html
+ 1
+
+ Cookies uploader dialog title
+
+
+ NOTE: Uploading new cookies will override your previous cookies. Also note that cookies are instance-wide, not per-user.
+ 참고: 새로운 쿠키를 추가하면 이전 쿠키를 덮어씁니다. 또한 쿠키는 사용자 개인이 아닌 전체에 적용됩니다.
+
+ src/app/dialogs/cookies-uploader-dialog/cookies-uploader-dialog.component.html
+ 20
+
+ Cookies upload warning
+
+
+ Drag and Drop
+ 드래그 앤 드롭
+
+ src/app/dialogs/cookies-uploader-dialog/cookies-uploader-dialog.component.html
+ 11
+
+ Drag and Drop
+
+
+ Modify playlist
+ 재생목록 수정
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 1
+
+ Modify playlist dialog title
+
+
+ Save
+ 저장
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 43
+
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 68
+
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 56
+
+
+ src/app/settings/settings.component.html
+ 464
+
+
+ src/app/components/modify-users/modify-users.component.html
+ 58
+
+ Save
+
+
+ Randomize order when playing
+ 재생할 때 재생목록 섞기
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 13
+
+ Randomize order when playing checkbox label
+
+
+ Add content
+ 콘텐츠 추가
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 24
+
+ Add content
+
+
+ Normal order
+ 기본 순서
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 18
+
+ Normal order
+
+
+ Reverse order
+ 순서 거꾸로
+
+ src/app/dialogs/modify-playlist/modify-playlist.component.html
+ 19
+
+ Reverse order
+
+
+ My videos
+ 내 동영상
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 20
+
+ My videos title
+
+
+ Search
+ 검색
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 24
+
+
+ src/app/components/modify-users/modify-users.component.html
+ 7
+
+
+ src/app/subscription/subscription/subscription.component.html
+ 33
+
+ Files search placeholder
+
+
+ No videos found.
+ 동영상 없음.
+
+ src/app/components/recent-videos/recent-videos.component.html
+ 38
+
+ No videos found
+
+
+ Editing
+ 수정중
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 1
+
+ Edit subscription dialog title prefix
+
+
+ Paused
+ 일시정지됨
+
+ src/app/dialogs/edit-subscription-dialog/edit-subscription-dialog.component.html
+ 7
+
+ Paused subscription setting
+
+
+ Editing category
+ 카테고리 수정중
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 1
+
+ Editing category dialog title
+
+
+ Rules
+ 규칙
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 10
+
+ Rules
+
+
+ Add new rule
+ 새로운 규칙 추가
+
+ src/app/dialogs/edit-category-dialog/edit-category-dialog.component.html
+ 39
+
+ Add new rule tooltip
+
+
+ Download Twitch Chat
+ 트위치 채팅 다운로드
+
+ src/app/components/twitch-chat/twitch-chat.component.html
+ 10
+
+ Download Twitch Chat button
+
+
+ Edit
+ 수정
+
+ src/app/file-card/file-card.component.html
+ 19
+
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 37
+
+ Playlist edit button
+
+
+ Delete
+ 삭제
+
+ src/app/file-card/file-card.component.html
+ 20
+
+
+ src/app/file-card/file-card.component.html
+ 25
+
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 33
+
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 39
+
+ Delete playlist
+
+
+ Info
+ 정보
+
+ src/app/file-card/file-card.component.html
+ 24
+
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 24
+
+
+ src/app/subscription/subscription-file-card/subscription-file-card.component.html
+ 7
+
+ Video info button
+
+
+ Count:
+ 동영상 수:
+
+ src/app/file-card/file-card.component.html
+ 8
+
+ Playlist video count
+
+
+ Delete and blacklist
+ 삭제하고 블랙리스트 추가
+
+ src/app/file-card/file-card.component.html
+ 26
+
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 34
+
+ Delete and blacklist video button
+
+
+ views
+ 조회수
+
+ src/app/player/player.component.html
+ 15
+
+ View count label
+
+
+ The download was successful
+ 성공적으로 다운로드 완료
+
+ src/app/download-item/download-item.component.html
+ 8
+
+
+ src/app/download-item/download-item.component.html
+ 8
+
+ download successful tooltip
+
+
+ An error has occurred
+ 에러 발생
+
+ src/app/download-item/download-item.component.html
+ 9
+
+
+ src/app/download-item/download-item.component.html
+ 9
+
+ download error tooltip
+
+
+ Details
+ 세부사항
+
+ src/app/download-item/download-item.component.html
+ 18
+
+ Details
+
+
+ An error has occurred:
+ 에러 발생:
+
+ src/app/download-item/download-item.component.html
+ 27
+
+ Error label
+
+
+ Download start:
+ 다운로드 시작:
+
+ src/app/download-item/download-item.component.html
+ 32
+
+ Download start label
+
+
+ Download end:
+ 다운로드 끝:
+
+ src/app/download-item/download-item.component.html
+ 35
+
+ Download end label
+
+
+ File path(s):
+ 파일 경로(들):
+
+ src/app/download-item/download-item.component.html
+ 38
+
+ File path(s) label
+
+
+ Your subscriptions
+ 구독중
+
+ src/app/subscriptions/subscriptions.component.html
+ 3
+
+ Subscriptions title
+
+
+ Channels
+ 채널
+
+ src/app/subscriptions/subscriptions.component.html
+ 8
+
+ Subscriptions channels title
+
+
+ Playlists
+ 재생목록
+
+ src/app/subscriptions/subscriptions.component.html
+ 27
+
+ Subscriptions playlists title
+
+
+ Name not available. Channel retrieval in progress.
+ 이름이 유효하지 않음. 채널 검색중.
+
+ src/app/subscriptions/subscriptions.component.html
+ 14
+
+ Subscription playlist not available text
+
+
+ You have no channel subscriptions.
+ 구독중인 채널이 없습니다.
+
+ src/app/subscriptions/subscriptions.component.html
+ 24
+
+ No channel subscriptions text
+
+
+ Name not available. Playlist retrieval in progress.
+ 이름이 유효하지 않음. 플레이리스트 검색중.
+
+ src/app/subscriptions/subscriptions.component.html
+ 33
+
+ Subscription playlist not available text
+
+
+ You have no playlist subscriptions.
+ 구독중인 재생목록이 없습니다.
+
+ src/app/subscriptions/subscriptions.component.html
+ 43
+
+ No playlist subscriptions text
+
+
+ Main
+ 메인
+
+ src/app/settings/settings.component.html
+ 12
+
+ Main settings label
+
+
+ Downloader
+ 다운로더
+
+ src/app/settings/settings.component.html
+ 102
+
+ Downloader settings label
+
+
+ Extra
+ 추가
+
+ src/app/settings/settings.component.html
+ 185
+
+ Extra settings label
+
+
+ Database
+ 데이터베이스
+
+ src/app/settings/settings.component.html
+ 284
+
+ Database settings label
+
+
+ Advanced
+ 고급
+
+ src/app/settings/settings.component.html
+ 320
+
+ Host settings label
+
+
+ Users
+ 사용자
+
+ src/app/settings/settings.component.html
+ 403
+
+
+ src/app/settings/settings.component.html
+ 403
+
+ Users settings label
+
+
+ Logs
+ 로그
+
+ src/app/settings/settings.component.html
+ 451
+
+
+ src/app/settings/settings.component.html
+ 451
+
+ Logs settings label
+
+
+ {VAR_SELECT, select, true {Close} false {Cancel} other {otha}}
+ {VAR_SELECT, select, true {닫다} false {취소} other {기타}}
+
+ src/app/settings/settings.component.html
+ 467
+
+ Settings cancel and close button
+
+
+ URL this app will be accessed from, without the port.
+ 포트를 제외한 이 앱에 접속할 URL.
+
+ src/app/settings/settings.component.html
+ 19
+
+ URL setting input hint
+
+
+ Port
+ 포트
+
+ src/app/settings/settings.component.html
+ 24
+
+ Port input placeholder
+
+
+ The desired port. Default is 17442.
+ 포트 설정. 기본 포트는 17442 입니다.
+
+ src/app/settings/settings.component.html
+ 25
+
+ Port setting input hint
+
+
+ Multi-user mode
+ 복수 사용자 모드
+
+ src/app/settings/settings.component.html
+ 34
+
+ Multi user mode setting
+
+
+ Users base path
+ 사용자 기본 경로
+
+ src/app/settings/settings.component.html
+ 38
+
+ Users base path placeholder
+
+
+ Base path for users and their downloaded videos.
+ 사용자와 그들의 동영상 다운로드를 위한 기본 경로.
+
+ src/app/settings/settings.component.html
+ 39
+
+ Users base path hint
+
+
+ Allow subscriptions
+ 구독 허용
+
+ src/app/settings/settings.component.html
+ 48
+
+ Allow subscriptions setting
+
+
+ Subscriptions base path
+ 구독 기본 경로
+
+ src/app/settings/settings.component.html
+ 52
+
+ Subscriptions base path input setting placeholder
+
+
+ Base path for videos from your subscribed channels and playlists. It is relative to YTDL-Material's root folder.
+ 구독된 채널과 재생목록에서 나온 영상들을 위한 기본 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.
+
+ src/app/settings/settings.component.html
+ 53
+
+ Subscriptions base path setting input hint
+
+
+ Check interval
+ 확인 간격
+
+ src/app/settings/settings.component.html
+ 58
+
+ Check interval input setting placeholder
+
+
+ Unit is seconds, only include numbers.
+ 단위는 초이며, 숫자만 넣으세요.
+
+ src/app/settings/settings.component.html
+ 59
+
+ Check interval setting input hint
+
+
+ Sometimes new videos are downloaded before being fully processed. This setting will mean new videos will be checked for a higher quality version the following day.
+ 가끔 새 동영상이 최고 화질 처리 전에 다운로드 될 때가 있습니다. 이 설정은 새 동영상이 더 높은 화질의 버전이 있는지 다음 날짜에 확인됨을 의미합니다.
+
+ src/app/settings/settings.component.html
+ 63
+
+ Redownload fresh uploads tooltip
+
+
+ Redownload fresh uploads
+ 높은 화질 재다운로드
+
+ src/app/settings/settings.component.html
+ 63
+
+ Redownload fresh uploads
+
+
+ Theme
+ 테마
+
+ src/app/settings/settings.component.html
+ 72
+
+ Theme select label
+
+
+ Default
+ 기본
+
+ src/app/settings/settings.component.html
+ 74
+
+ Default theme label
+
+
+ Allow theme change
+ 테마 변경 허용
+
+ src/app/settings/settings.component.html
+ 80
+
+ Allow theme change setting
+
+
+ Language
+ 언어
+
+ src/app/settings/settings.component.html
+ 89
+
+ Language select label
+
+
+ Audio folder path
+ 오디오 폴더 경로
+
+ src/app/settings/settings.component.html
+ 109
+
+ Audio folder path input placeholder
+
+
+ Path for audio only downloads. It is relative to YTDL-Material's root folder.
+ 오디오 전용 다운로드 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.
+
+ src/app/settings/settings.component.html
+ 110
+
+ Aduio path setting input hint
+
+
+ Video folder path
+ 동영상 폴더 경로
+
+ src/app/settings/settings.component.html
+ 116
+
+ Video folder path input placeholder
+
+
+ Path for video downloads. It is relative to YTDL-Material's root folder.
+ 동영상 다운로드 경로. 경로는 YTDL-Material 루트 폴더 경로에 상대적입니다.
+
+ src/app/settings/settings.component.html
+ 117
+
+ Video path setting input hint
+
+
+ Default file output
+ 기본 파일 출력
+
+ src/app/settings/settings.component.html
+ 123
+
+ Default file output placeholder
+
+
+ Path is relative to the above download paths. Don't include extension.
+ 경로는 위의 다운로드 경로에 상대적입니다. 확장자는 포함하지 마세요.
+
+ src/app/settings/settings.component.html
+ 126
+
+ Custom Output input hint
+
+
+ Global custom args
+ 전반적으로 적용될 사용자 지정 인수
+
+ src/app/settings/settings.component.html
+ 133
+
+ Custom args input placeholder
+
+
+ Global custom args for downloads on the home page. Args are delimited using two commas like so: ,,
+ 홈페이지에서의 다운로드에 대해 전반적으로 적용될 사용자 지정 인수. 인수는 다음과 같은 두 개의 쉼표를 사용하여 구분됩니다. : ,,
+
+ src/app/settings/settings.component.html
+ 134
+
+ Custom args setting input hint
+
+
+ Categories
+ 카테고리
+
+ src/app/settings/settings.component.html
+ 144
+
+ Categories
+
+
+ With this setting enabled, if a single video matches a category, the entire playlist will receive that category.
+ 이 설정을 사용하면, 하나의 동영상이 카테고리와 일치할 경우, 전체 재생목록에 해당 카테고리가 표시됩니다.
+
+ src/app/settings/settings.component.html
+ 158
+
+ Allow playlist categorization setting tooltip
+
+
+ Allow playlist categorization
+ 재생목록 카테고리화 허용
+
+ src/app/settings/settings.component.html
+ 158
+
+ Allow playlist categorization setting label
+
+
+ Use youtube-dl archive
+ Youtube-dl 아카이브 사용
+
+ src/app/settings/settings.component.html
+ 166
+
+ Use youtubedl archive setting
+
+
+ Include thumbnail
+ 썸네일 포함
+
+ src/app/settings/settings.component.html
+ 170
+
+ Include thumbnail setting
+
+
+ Include metadata
+ 메타데이터 포함
+
+ src/app/settings/settings.component.html
+ 174
+
+ Include metadata setting
+
+
+ Kill all downloads
+ 모든 다운로드 종료
+
+ src/app/settings/settings.component.html
+ 178
+
+ Kill all downloads button
+
+
+ Top title
+ 상위 제목
+
+ src/app/settings/settings.component.html
+ 191
+
+ Top title input placeholder
+
+
+ File manager enabled
+ 파일 매니저 설정됨
+
+ src/app/settings/settings.component.html
+ 196
+
+ File manager enabled setting
+
+
+ Downloads manager enabled
+ 다운로드 매니저 설정됨
+
+ src/app/settings/settings.component.html
+ 199
+
+ Downloads manager enabled setting
+
+
+ Allow quality select
+ 화질 선택 허용
+
+ src/app/settings/settings.component.html
+ 202
+
+ Allow quality seelct setting
+
+
+ Download only mode
+ 다운로드 전용 모드
+
+ src/app/settings/settings.component.html
+ 205
+
+ Download only mode setting
+
+
+ Allow multi-download mode
+ 복수 다운로드 모드 허용
+
+ src/app/settings/settings.component.html
+ 208
+
+ Allow multi-download mode setting
+
+
+ Enable Public API
+ 오픈 API 허용
+
+ src/app/settings/settings.component.html
+ 216
+
+ Enable Public API key setting
+
+
+ Public API Key
+ 오픈 API 키
+
+ src/app/settings/settings.component.html
+ 221
+
+ Public API Key setting placeholder
+
+
+ View documentation
+ 문서 보기
+
+ src/app/settings/settings.component.html
+ 222
+
+ View API docs setting hint
+
+
+ This will delete your old API key!
+ 이것은 예전 API키를 지울 것입니다!
+
+ src/app/settings/settings.component.html
+ 226
+
+ delete api key tooltip
+
+
+ Generate
+ 생성
+
+ src/app/settings/settings.component.html
+ 226
+
+ Generate key button
+
+
+ Use YouTube API
+ 유튜브 API 사용
+
+ src/app/settings/settings.component.html
+ 235
+
+ Use YouTube API setting
+
+
+ Youtube API Key
+ 유튜브 API 키
+
+ src/app/settings/settings.component.html
+ 239
+
+ Youtube API Key setting placeholder
+
+
+ Generating a key is easy!
+ 키를 만드는 것은 쉽습니다!
+
+ src/app/settings/settings.component.html
+ 240
+
+
+ src/app/settings/settings.component.html
+ 252
+
+ Youtube API Key setting hint
+
+
+ Use Twitch API
+ 트위치 API 사용
+
+ src/app/settings/settings.component.html
+ 244
+
+ Use Twitch API setting
+
+
+ Twitch API Key
+ 트위치 API 키
+
+ src/app/settings/settings.component.html
+ 251
+
+ Twitch API Key setting placeholder
+
+
+ Also known as a Client ID.
+ 클라이언트 ID라고도 알려져 있음.
+
+ src/app/settings/settings.component.html
+ 252
+
+ Twitch API Key setting hint AKA preamble
+
+
+ Auto-download Twitch Chat
+ 트위치 채팅 자동 다운로드
+
+ src/app/settings/settings.component.html
+ 247
+
+ Auto download Twitch Chat setting
+
+
+ Click here
+ 이곳을 누르세요
+
+ src/app/settings/settings.component.html
+ 262
+
+
+ src/app/settings/settings.component.html
+ 268
+
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 25
+
+ Chrome ext click here
+
+
+ to download the official YoutubeDL-Material Chrome extension manually.
+ 공식 YoutubeDL-Material 크롬 확장 프로그램을 수동으로 다운로드 하기 위해.
+
+ src/app/settings/settings.component.html
+ 262
+
+ Chrome click here suffix
+
+
+ You must manually load the extension and modify the extension's settings to set the frontend URL.
+ 반드시 확장 프로그램을 수동으로 실행하고 확장 프로그램 설정을 수정하여 프론트엔드 URL을 설정해야 합니다.
+
+ src/app/settings/settings.component.html
+ 263
+
+ Chrome setup suffix
+
+
+ to install the official YoutubeDL-Material Firefox extension right off the Firefox extensions page.
+ 파이어폭스 확장 프로그램 페이지에서 바로 공식 YoutubeDL-Material 파이어폭스 확장 프로그램을 설치하기 위해.
+
+ src/app/settings/settings.component.html
+ 268
+
+ Firefox click here suffix
+
+
+ Detailed setup instructions.
+ 자세한 설정 지침.
+
+ src/app/settings/settings.component.html
+ 269
+
+ Firefox setup prefix link
+
+
+ Not much is required other than changing the extension's settings to set the frontend URL.
+ 프론트엔드 URL을 설정하기 위해 확장 프로그램 설정을 변경하는 것 외에는 필요한 것이 많지 않습니다.
+
+ src/app/settings/settings.component.html
+ 269
+
+ Firefox setup suffix
+
+
+ Drag the link below to your bookmarks, and you're good to go! Just navigate to the YouTube video you'd like to download, and click the bookmark.
+ 아래 링크를 북마크에 끌어다 놓으시면 됩니다! 이제 그냥 다운로드하고자 하는 유튜브 비디오 페이지에서 북마크를 클릭하면 됩니다.
+
+ src/app/settings/settings.component.html
+ 274
+
+ Bookmarklet instructions
+
+
+ Generate 'audio only' bookmarklet
+ '오디오 전용' 북마크 생성
+
+ src/app/settings/settings.component.html
+ 275
+
+ Generate audio only bookmarklet checkbox
+
+
+ Database location:
+ 데이터베이스 위치:
+
+ src/app/settings/settings.component.html
+ 290
+
+ Database location label
+
+
+ Records per table
+ 테이블당 레코드
+
+ src/app/settings/settings.component.html
+ 291
+
+ Records per table label
+
+
+ MongoDB Connection String
+ 몽고DB 연결 문자열
+
+ src/app/settings/settings.component.html
+ 299
+
+ MongoDB Connection String
+
+
+ Example:
+ 예시:
+
+ src/app/settings/settings.component.html
+ 300
+
+ MongoDB Connection String setting hint AKA preamble
+
+
+ Test connection string
+ 연결 문자열 테스트
+
+ src/app/settings/settings.component.html
+ 304
+
+ Test connection string button
+
+
+ Transfer DB to
+ DB 전환
+
+ src/app/settings/settings.component.html
+ 308
+
+ Transfer DB button
+
+
+ Database information could not be retrieved. Check the server logs for more information.
+ 데이터베이스 정보를 검색할 수 없습니다. 자세한 내용은 서버 로그를 확인하세요.
+
+ src/app/settings/settings.component.html
+ 312
+
+ Database info not retrieved error message
+
+
+ Select a downloader
+ 다운로더 선택
+
+ src/app/settings/settings.component.html
+ 326
+
+ Default downloader select label
+
+
+ Use default downloading agent
+ 기본 다운로드 에이전트 사용
+
+ src/app/settings/settings.component.html
+ 335
+
+ Use default downloading agent setting
+
+
+ Select a download agent
+ 다운로드 에이전트 선택
+
+ src/app/settings/settings.component.html
+ 339
+
+ Custom downloader select label
+
+
+ Log Level
+ 로그 레벨
+
+ src/app/settings/settings.component.html
+ 353
+
+ Log Level label
+
+
+ Login expiration
+ 로그인 만료
+
+ src/app/settings/settings.component.html
+ 365
+
+ Login expiration select label
+
+
+ Allow advanced download
+ 고급 다운로드 허용
+
+ src/app/settings/settings.component.html
+ 376
+
+ Allow advanced downloading setting
+
+
+ Use Cookies
+ 쿠키 사용
+
+ src/app/settings/settings.component.html
+ 384
+
+ Use cookies setting
+
+
+ Set Cookies
+ 쿠키 설정
+
+ src/app/settings/settings.component.html
+ 385
+
+ Set cookies button
+
+
+ Restart server
+ 서버 재시작
+
+ src/app/settings/settings.component.html
+ 397
+
+ Restart server button
+
+
+ Allow user registration
+ 사용자 등록 허용
+
+ src/app/settings/settings.component.html
+ 407
+
+ Allow registration setting
+
+
+ Auth method
+ 인증 방법
+
+ src/app/settings/settings.component.html
+ 411
+
+ Auth method select
+
+
+ Internal
+ 내부
+
+ src/app/settings/settings.component.html
+ 413
+
+ Internal auth method
+
+
+ LDAP
+ LDAP
+
+ src/app/settings/settings.component.html
+ 416
+
+ LDAP auth method
+
+
+ LDAP URL
+ LDAP URL
+
+ src/app/settings/settings.component.html
+ 423
+
+ LDAP URL
+
+
+ Bind DN
+ Bind DN
+
+ src/app/settings/settings.component.html
+ 428
+
+ Bind DN
+
+
+ Bind Credentials
+ Bind Credentials
+
+ src/app/settings/settings.component.html
+ 433
+
+ Bind Credentials
+
+
+ Search Base
+ 기본 검색
+
+ src/app/settings/settings.component.html
+ 438
+
+ Search Base
+
+
+ Search Filter
+ 검색 필터
+
+ src/app/settings/settings.component.html
+ 443
+
+ Search Filter
+
+
+ About YoutubeDL-Material
+ YoutubeDL-Material에 대하여
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 1
+
+ About dialog title
+
+
+ is an open-source YouTube downloader built under Google's Material Design specifications. You can seamlessly download your favorite videos as video or audio files, and even subscribe to your favorite channels and playlists to keep updated with their new videos.
+ 은(는) 구글의 Material 디자인 요건에 따라 만들어진 오픈소스 유튜브 다운로더 입니다. 당신은 당신이 좋아하는 동영상을 동영상이나 오디오 파일로 원활하게 받을 수 있으며, 심지어 당신이 좋아하는 채널이나 재생목록을 구독해 그들의 새로운 동영상을 지속적으로 업데이트 할 수도 있습니다.
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 12
+
+ About first paragraph
+
+
+ has some awesome features included! An extensive API, Docker support, and localization (translation) support. Read up on all the supported features by clicking on the GitHub icon above.
+ 은(는) 광범위한 API, 도커 지원, 현지화 (번역) 지원을 포함한 몇몇 엄청난 기능이 포함되어 있습니다! 아래 깃허브 아이콘을 클릭해 모든 지원되는 기능을 확인해보세요.
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 15
+
+ About second paragraph
+
+
+ Installed version:
+ 설치된 버전:
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 20
+
+ Version label
+
+
+ Found a bug or have a suggestion?
+ 버그를 찾았거나 제안하실 사항이 있으신가요?
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 25
+
+ About bug prefix
+
+
+ to create an issue!
+ 이슈를 생성하기 위해!
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 25
+
+ About bug suffix
+
+
+ Checking for updates...
+ 업데이트 확인중...
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 20
+
+ Checking for updates text
+
+
+ Update available
+ 업데이트 가능
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 21
+
+ View latest update
+
+
+ You can update from the settings menu.
+ 설정 메뉴에서 업데이트를 할 수 있습니다.
+
+ src/app/dialogs/about-dialog/about-dialog.component.html
+ 21
+
+ Update through settings menu hint
+
+
+ Select a version:
+ 선택된 버전:
+
+ src/app/updater/updater.component.html
+ 3
+
+ Select a version
+
+
+ Enable sharing
+ 공유 허용
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 9
+
+ Enable sharing checkbox
+
+
+ Use timestamp
+ 타임스탬프 사용
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 12
+
+ Use timestamp
+
+
+ Seconds
+ 초
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 14
+
+ Seconds
+
+
+ Copy to clipboard
+ 클립보드에 복사
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 23
+
+ Copy to clipboard button
+
+
+ Share playlist
+ 재생목록 공유
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 2
+
+ Share playlist dialog title
+
+
+ Share file
+ 파일 공유
+
+ src/app/dialogs/share-media-dialog/share-media-dialog.component.html
+ 3
+
+ Share video dialog title
+
+
+ Session ID:
+ 세션 아이디:
+
+ src/app/components/downloads/downloads.component.html
+ 5
+
+ Session ID
+
+
+ Clear all downloads
+ 모든 다운로드된 항목 지우기
+
+ src/app/components/downloads/downloads.component.html
+ 18
+
+ clear all downloads action button
+
+
+ (current)
+ (현재)
+
+ src/app/components/downloads/downloads.component.html
+ 6
+
+ Current session
+
+
+ No downloads available!
+ 다운로드된 항목 없음!
+
+ src/app/components/downloads/downloads.component.html
+ 25
+
+ No downloads label
+
+
+ Your Profile
+ 프로필
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 1
+
+ User profile dialog title
+
+
+ Logout
+ 로그아웃
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 28
+
+ Logout
+
+
+ UID:
+ UID:
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 9
+
+ UID
+
+
+ Created:
+ 생성됨:
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 12
+
+ Created
+
+
+ You are not logged in.
+ 로그인하지 않았습니다.
+
+ src/app/dialogs/user-profile-dialog/user-profile-dialog.component.html
+ 19
+
+ Not logged in notification
+
+
+ Create admin account
+ 관리자 계정 생성
+
+ src/app/dialogs/set-default-admin-dialog/set-default-admin-dialog.component.html
+ 1
+
+ Create admin account dialog title
+
+
+ No default admin account detected. This will create and set the password for an admin account with the user name as 'admin'.
+ 기본 관리자 계정이 감지되지 않았습니다. 이것은 'admin'이라는 ID를 가진 관리자 계정을 만들고, 비밀번호를 설정할 것입니다.
+
+ src/app/dialogs/set-default-admin-dialog/set-default-admin-dialog.component.html
+ 5
+
+ No default admin detected explanation
+
+
+ Create
+ 생성
+
+ src/app/dialogs/set-default-admin-dialog/set-default-admin-dialog.component.html
+ 17
+
+ Create
+
+
+ Add Users
+ 사용자 추가
+
+ src/app/components/modify-users/modify-users.component.html
+ 90
+
+ Add users button
+
+
+ Edit Role
+ 역할 수정
+
+ src/app/components/modify-users/modify-users.component.html
+ 95
+
+ Edit role
+
+
+ User name
+ ID
+
+ src/app/components/modify-users/modify-users.component.html
+ 17
+
+ Username users table header
+
+
+ Role
+ 역할
+
+ src/app/components/modify-users/modify-users.component.html
+ 35
+
+ Role users table header
+
+
+ Actions
+ 액션
+
+ src/app/components/modify-users/modify-users.component.html
+ 55
+
+ Actions users table header
+
+
+ Manage user
+ 사용자 관리
+
+ src/app/components/modify-users/modify-users.component.html
+ 70
+
+
+ src/app/components/manage-user/manage-user.component.html
+ 1
+
+ manage user action button tooltip
+
+
+ Delete user
+ 사용자 삭제
+
+ src/app/components/modify-users/modify-users.component.html
+ 73
+
+ delete user action button tooltip
+
+
+ Edit user
+ 사용자 수정
+
+ src/app/components/modify-users/modify-users.component.html
+ 66
+
+ edit user action button tooltip
+
+
+ User UID:
+ 사용자 UID:
+
+ src/app/components/manage-user/manage-user.component.html
+ 4
+
+ User UID
+
+
+ New password
+ 새 비밀번호
+
+ src/app/components/manage-user/manage-user.component.html
+ 8
+
+ New password placeholder
+
+
+ Set new password
+ 새 비밀번호 설정
+
+ src/app/components/manage-user/manage-user.component.html
+ 10
+
+ Set new password
+
+
+ Use role default
+ 기본 역할 사용
+
+ src/app/components/manage-user/manage-user.component.html
+ 19
+
+ Use role default
+
+
+ Yes
+ 네
+
+ src/app/components/manage-user/manage-user.component.html
+ 20
+
+
+ src/app/components/manage-role/manage-role.component.html
+ 9
+
+ Yes
+
+
+ No
+ 아니오
+
+ src/app/components/manage-user/manage-user.component.html
+ 21
+
+
+ src/app/components/manage-role/manage-role.component.html
+ 10
+
+ No
+
+
+ Manage role
+ 역할 관리
+
+ src/app/components/manage-role/manage-role.component.html
+ 1
+
+ Manage role dialog title
+
+
+ Lines:
+ 줄:
+
+ src/app/components/logs-viewer/logs-viewer.component.html
+ 22
+
+ Label for lines select in logger view
+
+
+ Clear logs
+ 로그 지우기
+
+ src/app/components/logs-viewer/logs-viewer.component.html
+ 34
+
+ Clear logs button
+
+
+ Auto-generated
+ 자동으로 생성됨
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 5
+
+ Auto-generated label
+
+
+ Open file
+ 파일 열기
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 18
+
+ Open file button
+
+
+ Open file in new tab
+ 새 탭에서 파일 열기
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 19
+
+ Open file in new tab
+
+
+ Go to subscription
+ 구독중으로 가기
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 25
+
+ Go to subscription menu item
+
+
+ Delete and redownload
+ 삭제하고 재다운로드
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 28
+
+
+ src/app/subscription/subscription-file-card/subscription-file-card.component.html
+ 8
+
+ Delete and redownload subscription video button
+
+
+ Delete forever
+ 영원히 삭제
+
+ src/app/components/unified-file-card/unified-file-card.component.html
+ 31
+
+
+ src/app/subscription/subscription-file-card/subscription-file-card.component.html
+ 9
+
+ Delete forever subscription video button
+
+
+ See more.
+ 더 보기.
+
+ src/app/components/see-more/see-more.component.html
+ 5,6
+
+ See more
+
+
+ See less.
+ 간략히 보기.
+
+ src/app/components/see-more/see-more.component.html
+ 8,9
+
+ See less
+
+
+ Length:
+ 길이:
+
+ src/app/subscription/subscription-file-card/subscription-file-card.component.html
+ 3
+
+ Video duration label
+
+
+
+