shifro 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -9
- package/dist/cli.mjs +10 -5
- package/dist/index.cjs +7 -8
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +9 -5
- package/package.json +23 -18
package/README.md
CHANGED
|
@@ -23,7 +23,8 @@ Run `npm install shifro` to install the library as dependency for your project.
|
|
|
23
23
|
#### Decrypting file using Node.js streams
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
|
-
import { Decryption,
|
|
26
|
+
import { Decryption, FilePathSource, FilePathTarget, Input, Output } from 'shifro';
|
|
27
|
+
import type { Key, KeyId } from 'shifro';
|
|
27
28
|
|
|
28
29
|
async function decrypt() {
|
|
29
30
|
const decryption = await Decryption.init({
|
|
@@ -32,12 +33,21 @@ async function decrypt() {
|
|
|
32
33
|
keys: new Map<KeyId, Key>([
|
|
33
34
|
['4d97930a3d7b55fa81d0028653f5e499', '429ec76475e7a952d224d8ef867f12b6'],
|
|
34
35
|
['d21373c0b8ab5ba9954742bcdfb5f48b', '150a6c7d7dee6a91b74dccfce5b31928'],
|
|
35
|
-
])
|
|
36
|
+
]),
|
|
37
|
+
// Optinally, you can use this callback to handle encryption information (like key ID and PSSH boxes)
|
|
38
|
+
handleEncryptionInfo: ({ keyId, psshBoxes }) => {
|
|
39
|
+
console.group(`Key ID: ${keyId}`);
|
|
40
|
+
for (const psshBox of psshBoxes) {
|
|
41
|
+
console.log(`PSSH box: ${psshBox.systemId} (${psshBox.data.length} bytes)`);
|
|
42
|
+
}
|
|
43
|
+
console.groupEnd();
|
|
44
|
+
},
|
|
36
45
|
}),
|
|
37
46
|
output: new Output({ target: new FilePathTarget('./output.mp4') }),
|
|
38
47
|
});
|
|
39
48
|
|
|
40
|
-
decryption.onProgress = (progress) =>
|
|
49
|
+
decryption.onProgress = (progress) =>
|
|
50
|
+
process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`);
|
|
41
51
|
|
|
42
52
|
await decryption.execute();
|
|
43
53
|
}
|
|
@@ -46,7 +56,8 @@ async function decrypt() {
|
|
|
46
56
|
#### Decrypting file using browser's Web Streams API
|
|
47
57
|
|
|
48
58
|
```ts
|
|
49
|
-
import { Decryption, Input,
|
|
59
|
+
import { Decryption, Input, Output, ReadableStreamSource, StreamTarget } from 'shifro';
|
|
60
|
+
import type { Key, KeyId } from 'shifro';
|
|
50
61
|
|
|
51
62
|
async function decryptFromBrowser() {
|
|
52
63
|
const handleFileSelect = async () => {
|
|
@@ -54,12 +65,15 @@ async function decryptFromBrowser() {
|
|
|
54
65
|
const input = document.querySelector<HTMLInputElement>('#input')!;
|
|
55
66
|
input.addEventListener('change', () => resolve(input.files![0]));
|
|
56
67
|
});
|
|
57
|
-
}
|
|
68
|
+
};
|
|
58
69
|
|
|
59
70
|
const inputFile = await handleFileSelect();
|
|
60
71
|
const inputReadableStream = inputFile.stream();
|
|
61
72
|
|
|
62
|
-
const outputFileHandle = window.showSaveFilePicker({
|
|
73
|
+
const outputFileHandle = window.showSaveFilePicker({
|
|
74
|
+
suggestedName: 'output.mp4',
|
|
75
|
+
startIn: 'downloads',
|
|
76
|
+
});
|
|
63
77
|
const outputWritableStream = await outputFileHandle.createWritable();
|
|
64
78
|
|
|
65
79
|
const decryption = await Decryption.init({
|
|
@@ -68,18 +82,18 @@ async function decryptFromBrowser() {
|
|
|
68
82
|
keys: new Map<KeyId, Key>([
|
|
69
83
|
['4d97930a3d7b55fa81d0028653f5e499', '429ec76475e7a952d224d8ef867f12b6'],
|
|
70
84
|
['d21373c0b8ab5ba9954742bcdfb5f48b', '150a6c7d7dee6a91b74dccfce5b31928'],
|
|
71
|
-
])
|
|
85
|
+
]),
|
|
72
86
|
}),
|
|
73
87
|
output: new Output({ target: new StreamTarget(outputWritableStream) }),
|
|
74
88
|
});
|
|
75
89
|
|
|
76
|
-
decryption.onProgress = (progress) =>
|
|
90
|
+
decryption.onProgress = (progress) =>
|
|
91
|
+
console.log(`Decrypting... [${Math.round(progress * 100)}%]`);
|
|
77
92
|
|
|
78
93
|
await decryption.execute();
|
|
79
94
|
}
|
|
80
95
|
```
|
|
81
96
|
|
|
82
|
-
|
|
83
97
|
## Credits
|
|
84
98
|
|
|
85
99
|
- [mediabunny](https://github.com/Vanilagy/mediabunny)
|
package/dist/cli.mjs
CHANGED
|
@@ -3,16 +3,20 @@ import { parseArgs } from "node:util";
|
|
|
3
3
|
import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input, Mp4OutputFormat, Output } from "mediabunny";
|
|
4
4
|
//#region package.json
|
|
5
5
|
var name = "shifro";
|
|
6
|
-
var version = "1.
|
|
6
|
+
var version = "1.1.0";
|
|
7
7
|
var author = "Vitaly Gashkov <vitalygashkov@vk.com>";
|
|
8
8
|
//#endregion
|
|
9
|
-
//#region src/
|
|
9
|
+
//#region src/index.ts
|
|
10
10
|
var Input$1 = class extends Input {
|
|
11
|
-
constructor({ keys, ...options }) {
|
|
11
|
+
constructor({ keys, handleEncryptionInfo, ...options }) {
|
|
12
12
|
super({
|
|
13
13
|
...options,
|
|
14
14
|
formats: ALL_FORMATS,
|
|
15
|
-
formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
|
|
15
|
+
formatOptions: { isobmff: { resolveKeyId: ({ keyId, psshBoxes }) => {
|
|
16
|
+
handleEncryptionInfo?.({
|
|
17
|
+
keyId,
|
|
18
|
+
psshBoxes
|
|
19
|
+
});
|
|
16
20
|
const key = keys.get(keyId);
|
|
17
21
|
if (!key) throw new Error("Unknown key ID.");
|
|
18
22
|
return key;
|
|
@@ -56,7 +60,8 @@ const decryptFile = async () => {
|
|
|
56
60
|
}),
|
|
57
61
|
output: new Output$1({ target: new FilePathTarget(outputPath) })
|
|
58
62
|
});
|
|
59
|
-
decryption.onProgress = (progress) => process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`)
|
|
63
|
+
decryption.onProgress = (progress) => process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`);
|
|
64
|
+
await decryption.execute();
|
|
60
65
|
console.timeEnd("\nDone!");
|
|
61
66
|
};
|
|
62
67
|
const showHelp = () => {
|
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let mediabunny = require("mediabunny");
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/index.ts
|
|
4
4
|
var Input = class extends mediabunny.Input {
|
|
5
|
-
constructor({ keys, ...options }) {
|
|
5
|
+
constructor({ keys, handleEncryptionInfo, ...options }) {
|
|
6
6
|
super({
|
|
7
7
|
...options,
|
|
8
8
|
formats: mediabunny.ALL_FORMATS,
|
|
9
|
-
formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
|
|
9
|
+
formatOptions: { isobmff: { resolveKeyId: ({ keyId, psshBoxes }) => {
|
|
10
|
+
handleEncryptionInfo?.({
|
|
11
|
+
keyId,
|
|
12
|
+
psshBoxes
|
|
13
|
+
});
|
|
10
14
|
const key = keys.get(keyId);
|
|
11
15
|
if (!key) throw new Error("Unknown key ID.");
|
|
12
16
|
return key;
|
|
@@ -27,17 +31,12 @@ exports.Decryption = mediabunny.Conversion;
|
|
|
27
31
|
exports.FilePathSource = mediabunny.FilePathSource;
|
|
28
32
|
exports.FilePathTarget = mediabunny.FilePathTarget;
|
|
29
33
|
exports.Input = Input;
|
|
30
|
-
exports.InputOptions = mediabunny.InputOptions;
|
|
31
34
|
exports.MkvOutputFormat = mediabunny.MkvOutputFormat;
|
|
32
35
|
exports.MovOutputFormat = mediabunny.MovOutputFormat;
|
|
33
36
|
exports.Mp3OutputFormat = mediabunny.Mp3OutputFormat;
|
|
34
37
|
exports.Mp4OutputFormat = mediabunny.Mp4OutputFormat;
|
|
35
38
|
exports.Output = Output;
|
|
36
|
-
exports.OutputFormat = mediabunny.OutputFormat;
|
|
37
|
-
exports.OutputOptions = mediabunny.OutputOptions;
|
|
38
39
|
exports.ReadableStreamSource = mediabunny.ReadableStreamSource;
|
|
39
40
|
exports.StreamSource = mediabunny.StreamSource;
|
|
40
|
-
exports.StreamSourceOptions = mediabunny.StreamSourceOptions;
|
|
41
41
|
exports.StreamTarget = mediabunny.StreamTarget;
|
|
42
|
-
exports.StreamTargetOptions = mediabunny.StreamTargetOptions;
|
|
43
42
|
exports.UrlSource = mediabunny.UrlSource;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
|
|
1
|
+
import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, PsshBox, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
|
|
2
2
|
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/index.d.ts
|
|
4
4
|
type KeyId = string;
|
|
5
5
|
type Key = string;
|
|
6
6
|
type KeyMap = Map<KeyId, Key>;
|
|
7
7
|
declare class Input extends Input$1 {
|
|
8
8
|
constructor({
|
|
9
9
|
keys,
|
|
10
|
+
handleEncryptionInfo,
|
|
10
11
|
...options
|
|
11
12
|
}: Omit<InputOptions, 'formats' | 'formatOptions'> & {
|
|
12
13
|
keys: KeyMap;
|
|
14
|
+
handleEncryptionInfo?: (options: {
|
|
15
|
+
keyId: string;
|
|
16
|
+
psshBoxes: PsshBox[];
|
|
17
|
+
}) => void;
|
|
13
18
|
});
|
|
14
19
|
}
|
|
15
20
|
declare class Output extends Output$1 {
|
|
@@ -20,4 +25,4 @@ declare class Output extends Output$1 {
|
|
|
20
25
|
});
|
|
21
26
|
}
|
|
22
27
|
//#endregion
|
|
23
|
-
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, InputOptions, Key, KeyId, KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource };
|
|
28
|
+
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, type InputOptions, type Key, type KeyId, type KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, type OutputFormat, type OutputOptions, ReadableStreamSource, StreamSource, type StreamSourceOptions, StreamTarget, type StreamTargetOptions, UrlSource };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
|
|
1
|
+
import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, PsshBox, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
|
|
2
2
|
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/index.d.ts
|
|
4
4
|
type KeyId = string;
|
|
5
5
|
type Key = string;
|
|
6
6
|
type KeyMap = Map<KeyId, Key>;
|
|
7
7
|
declare class Input extends Input$1 {
|
|
8
8
|
constructor({
|
|
9
9
|
keys,
|
|
10
|
+
handleEncryptionInfo,
|
|
10
11
|
...options
|
|
11
12
|
}: Omit<InputOptions, 'formats' | 'formatOptions'> & {
|
|
12
13
|
keys: KeyMap;
|
|
14
|
+
handleEncryptionInfo?: (options: {
|
|
15
|
+
keyId: string;
|
|
16
|
+
psshBoxes: PsshBox[];
|
|
17
|
+
}) => void;
|
|
13
18
|
});
|
|
14
19
|
}
|
|
15
20
|
declare class Output extends Output$1 {
|
|
@@ -20,4 +25,4 @@ declare class Output extends Output$1 {
|
|
|
20
25
|
});
|
|
21
26
|
}
|
|
22
27
|
//#endregion
|
|
23
|
-
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, InputOptions, Key, KeyId, KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource };
|
|
28
|
+
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, type InputOptions, type Key, type KeyId, type KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, type OutputFormat, type OutputOptions, ReadableStreamSource, StreamSource, type StreamSourceOptions, StreamTarget, type StreamTargetOptions, UrlSource };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input as Input$1,
|
|
2
|
-
//#region src/
|
|
1
|
+
import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input as Input$1, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, ReadableStreamSource, StreamSource, StreamTarget, UrlSource } from "mediabunny";
|
|
2
|
+
//#region src/index.ts
|
|
3
3
|
var Input = class extends Input$1 {
|
|
4
|
-
constructor({ keys, ...options }) {
|
|
4
|
+
constructor({ keys, handleEncryptionInfo, ...options }) {
|
|
5
5
|
super({
|
|
6
6
|
...options,
|
|
7
7
|
formats: ALL_FORMATS,
|
|
8
|
-
formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
|
|
8
|
+
formatOptions: { isobmff: { resolveKeyId: ({ keyId, psshBoxes }) => {
|
|
9
|
+
handleEncryptionInfo?.({
|
|
10
|
+
keyId,
|
|
11
|
+
psshBoxes
|
|
12
|
+
});
|
|
9
13
|
const key = keys.get(keyId);
|
|
10
14
|
if (!key) throw new Error("Unknown key ID.");
|
|
11
15
|
return key;
|
|
@@ -22,4 +26,4 @@ var Output = class extends Output$1 {
|
|
|
22
26
|
}
|
|
23
27
|
};
|
|
24
28
|
//#endregion
|
|
25
|
-
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input,
|
|
29
|
+
export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, ReadableStreamSource, StreamSource, StreamTarget, UrlSource };
|
package/package.json
CHANGED
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shifro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A lightweight library for decrypting MP4 files, directly in the browser",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
7
7
|
],
|
|
8
|
-
"scripts": {
|
|
9
|
-
"start": "node ./dist/cli.mjs",
|
|
10
|
-
"web": "vite",
|
|
11
|
-
"build": "npm run bundle:lib && npm run bundle:cli",
|
|
12
|
-
"bundle:lib": "tsdown ./src/index.ts --format cjs --format esm --dts --platform neutral",
|
|
13
|
-
"bundle:cli": "tsdown ./src/cli.ts --format esm --no-clean",
|
|
14
|
-
"build:cli": "npm run build:cli:mac && npm run build:cli:linux && npm run build:cli:win",
|
|
15
|
-
"build:cli:mac": "bun build --compile --minify --bytecode --target=bun-darwin-arm64 ./src/cli.ts --outfile shifro-windows.exe",
|
|
16
|
-
"build:cli:linux": "bun build --compile --minify --bytecode --target=bun-linux-x64 ./src/cli.ts --outfile shifro-linux",
|
|
17
|
-
"build:cli:win": "bun build --compile --minify --bytecode --target=bun-windows-x64 ./src/cli.ts --outfile shifro-macos",
|
|
18
|
-
"typecheck": "tsc --noEmit",
|
|
19
|
-
"test": "vitest",
|
|
20
|
-
"prepublishOnly": "npm run build"
|
|
21
|
-
},
|
|
22
8
|
"bin": {
|
|
23
9
|
"shifro": "./dist/cli.mjs"
|
|
24
10
|
},
|
|
@@ -74,12 +60,31 @@
|
|
|
74
60
|
"node": ">=22"
|
|
75
61
|
},
|
|
76
62
|
"dependencies": {
|
|
77
|
-
"mediabunny": "^1.42.0-beta.
|
|
63
|
+
"mediabunny": "^1.42.0-beta.7"
|
|
78
64
|
},
|
|
79
65
|
"devDependencies": {
|
|
80
66
|
"@types/node": "^24.5.2",
|
|
67
|
+
"oxfmt": "^0.46.0",
|
|
68
|
+
"oxlint": "^1.61.0",
|
|
81
69
|
"tsdown": "^0.21.10",
|
|
82
|
-
"typescript": "
|
|
70
|
+
"typescript": "~6.0.3",
|
|
83
71
|
"vitest": "^4.1.5"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"start": "node ./dist/cli.mjs",
|
|
75
|
+
"web": "vite",
|
|
76
|
+
"build": "pnpm run bundle:lib && pnpm run bundle:cli",
|
|
77
|
+
"bundle:lib": "tsdown ./src/index.ts --format cjs --format esm --dts --platform neutral",
|
|
78
|
+
"bundle:cli": "tsdown ./src/cli.ts --format esm --no-clean",
|
|
79
|
+
"build:cli": "pnpm run build:cli:mac && pnpm run build:cli:linux && pnpm run build:cli:win",
|
|
80
|
+
"build:cli:mac": "bun build --compile --minify --bytecode --target=bun-darwin-arm64 ./src/cli.ts --outfile shifro-windows.exe",
|
|
81
|
+
"build:cli:linux": "bun build --compile --minify --bytecode --target=bun-linux-x64 ./src/cli.ts --outfile shifro-linux",
|
|
82
|
+
"build:cli:win": "bun build --compile --minify --bytecode --target=bun-windows-x64 ./src/cli.ts --outfile shifro-macos",
|
|
83
|
+
"fmt": "oxfmt .",
|
|
84
|
+
"fmt:check": "oxfmt --check .",
|
|
85
|
+
"lint": "oxlint .",
|
|
86
|
+
"lint:fix": "oxlint --fix .",
|
|
87
|
+
"typecheck": "tsc --noEmit",
|
|
88
|
+
"test": "vitest"
|
|
84
89
|
}
|
|
85
|
-
}
|
|
90
|
+
}
|