mirror of
https://github.com/snobu/destreamer.git
synced 2026-01-29 19:32:16 +00:00
Compare commits
9 Commits
api_thrott
...
v3.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de6ab1d8af | ||
|
|
01014df068 | ||
|
|
f2b7a9ba96 | ||
|
|
b6c0dfe98d | ||
|
|
1fbe36629b | ||
|
|
4545b010b3 | ||
|
|
7fc7c4733a | ||
|
|
a9f8b02f08 | ||
|
|
5b62c50b22 |
40
README.md
40
README.md
@@ -2,13 +2,22 @@
|
||||
<img src="https://github.com/snobu/destreamer/workflows/Node%20CI/badge.svg" alt="CI build status" />
|
||||
</a>
|
||||
|
||||
# BREAKING
|
||||
|
||||
**destreamer v3.0** is just around the corner. Download speed improvement is astonishing and we have a never before seen photo from the design sessions:<br><br>
|
||||

|
||||
|
||||
Help us pick a codename for the new release:<br><br>
|
||||
<br><br>
|
||||
Comment in this thread: https://github.com/snobu/destreamer/issues/223
|
||||
|
||||

|
||||
|
||||
_(Alternative artwork proposals are welcome! Submit one through an Issue.)_
|
||||
|
||||
# Saves Microsoft Stream videos for offline enjoyment
|
||||
|
||||
### v2.1 Release, codename _Hammer of Dawn<sup>TM</sup>_
|
||||
### v2 Release, codename _Hammer of Dawn<sup>TM</sup>_
|
||||
|
||||
This release would not have been possible without the code and time contributed by two distinguished developers: [@lukaarma](https://github.com/lukaarma) and [@kylon](https://github.com/kylon). Thank you!
|
||||
|
||||
@@ -17,6 +26,7 @@ This release would not have been possible without the code and time contributed
|
||||
- [Politecnico di Milano][polimi]: fork over at https://github.com/SamanFekri/destreamer
|
||||
- [Università di Pisa][unipi]: fork over at https://github.com/Guray00/destreamer-unipi
|
||||
- [Università della Calabria][unical]: fork over at https://github.com/peppelongo96/UnicalDown
|
||||
- [Università degli Studi di Parma][unipr]: fork over at https://github.com/vRuslan/destreamer-unipr
|
||||
|
||||
## What's new
|
||||
### v2.2
|
||||
@@ -51,6 +61,33 @@ Note that destreamer won't run in an elevated (Administrator/root) shell. Runnin
|
||||
|
||||
**WSL** (Windows Subsystem for Linux) is not supported as it can't easily pop up a browser window. It *may* work by installing an X Window server (like [Xming][xming]) and exporting the default display to it (`export DISPLAY=:0`) before running destreamer. See [this issue for more on WSL v1 and v2][wsl].
|
||||
|
||||
## Can i plug in my own browser?
|
||||
|
||||
Yes, yes you can. This may be useful if your main browser has some authentication plugins that are required for you to logon to your Microsoft Stream tenant.
|
||||
To use your own browser for the authentication part, locate the following snippet in `src/destreamer.ts`:
|
||||
|
||||
```typescript
|
||||
const browser: puppeteer.Browser = await puppeteer.launch({
|
||||
executablePath: getPuppeteerChromiumPath(),
|
||||
headless: false,
|
||||
userDataDir: (argv.keepLoginCookies) ? chromeCacheFolder : undefined,
|
||||
args: [
|
||||
'--disable-dev-shm-usage',
|
||||
'--fast-start',
|
||||
'--no-sandbox'
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
Now, change `executablePath` to reflect the path to your browser and profile (i.e. to use Microsoft Edge on Windows):
|
||||
```typescript
|
||||
executablePath: "'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe' --profile-directory=Default",
|
||||
```
|
||||
|
||||
Note that for Mac/Linux the path will look a little different but no other changes are necessary.
|
||||
|
||||
You need to rebuild (`npm run build`) every time you change this configuration.
|
||||
|
||||
## How to build
|
||||
|
||||
To build destreamer clone this repository, install dependencies and run the build script -
|
||||
@@ -196,3 +233,4 @@ Please open an [issue](https://github.com/snobu/destreamer/issues) and we'll loo
|
||||
[polimi]: https://www.polimi.it
|
||||
[unipi]: https://www.unipi.it/
|
||||
[unical]: https://www.unical.it/portale/
|
||||
[unipr]: https://www.unipr.it/
|
||||
|
||||
@@ -34,6 +34,7 @@ export class ApiClient {
|
||||
return true;
|
||||
}
|
||||
logger.warn(`Got HTTP code ${err?.response?.status ?? undefined}. Retrying request...`);
|
||||
logger.verbose(`Here is the error message: \n '${err.response?.data}`);
|
||||
|
||||
const shouldRetry: boolean = retryCodes.includes(err?.response?.status ?? 0);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ export const argv: any = yargs.options({
|
||||
},
|
||||
closedCaptions: {
|
||||
alias: 'cc',
|
||||
describe: 'Check if closed captions are aviable and let the user choose which one to download (will not ask if only one aviable)',
|
||||
describe: 'Check if closed captions are available and let the user choose which one to download (will not ask if only one available)',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
demandOption: false
|
||||
@@ -183,8 +183,8 @@ function isOutputTemplateValid(argv: any): boolean {
|
||||
while (match) {
|
||||
if (!templateElements.includes(match[1])) {
|
||||
logger.error(
|
||||
`'${match[0]}' is not aviable as a template element \n` +
|
||||
`Aviable templates elements: '${templateElements.join("', '")}' \n`,
|
||||
`'${match[0]}' is not available as a template element \n` +
|
||||
`Available templates elements: '${templateElements.join("', '")}' \n`,
|
||||
{ fatal: true }
|
||||
);
|
||||
|
||||
|
||||
@@ -24,14 +24,14 @@ function publishedTimeToString(date: string): string {
|
||||
const minutes: string = dateJs.getMinutes().toString();
|
||||
const seconds: string = dateJs.getSeconds().toString();
|
||||
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
return `${hours}.${minutes}.${seconds}`;
|
||||
}
|
||||
|
||||
|
||||
function isoDurationToString(time: string): string {
|
||||
const duration: Duration = parseDuration(time);
|
||||
|
||||
return `${duration.hours ?? '00'}:${duration.minutes ?? '00'}:${duration.seconds?.toFixed(0) ?? '00'}`;
|
||||
return `${duration.hours ?? '00'}.${duration.minutes ?? '00'}.${duration.seconds?.toFixed(0) ?? '00'}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,8 +152,14 @@ export function createUniquePath(videos: Array<Video>, outDirs: Array<string>, t
|
||||
finalTitle = `${title}.${++i}`;
|
||||
}
|
||||
|
||||
const finalFileName = `${finalTitle}.${format}`;
|
||||
const cleanFileName = sanitizeWindowsName(finalFileName, { replacement: '_' });
|
||||
if (finalFileName !== cleanFileName) {
|
||||
logger.warn(`Not a valid Windows file name: "${finalFileName}".\nReplacing invalid characters with underscores to preserve cross-platform consistency.`);
|
||||
}
|
||||
|
||||
video.outPath = path.join(outDirs[index], finalFileName);
|
||||
|
||||
video.outPath = path.join(outDirs[index], finalTitle + '.' + format);
|
||||
});
|
||||
|
||||
return videos;
|
||||
|
||||
Reference in New Issue
Block a user