lrkmusic-ytpro 1.0.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 +36 -0
- package/bgplay.js +273 -0
- package/innertube.js +393 -0
- package/package.json +17 -0
- package/script.js +2739 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# lrkmusic-ytpro (npm package source)
|
|
2
|
+
|
|
3
|
+
Yahi folder **single source of truth** hai – isi me edit karo, isi se npm publish karo.
|
|
4
|
+
|
|
5
|
+
## Development (LRKmusics app ke saath)
|
|
6
|
+
|
|
7
|
+
- Isi folder me **script.js**, **bgplay.js**, **innertube.js** edit karo.
|
|
8
|
+
- **Debug build** run karte hi app inhi files ko use karegi (Gradle auto-copy karke `AppCode/app/src/main/assets/ytpro/` me daal deta hai).
|
|
9
|
+
- Koi alag copy step nahi – sirf is folder me change karo, phir app **Build → Run** (Debug).
|
|
10
|
+
|
|
11
|
+
## NPM publish (jab sab changes ready hon)
|
|
12
|
+
|
|
13
|
+
1. **Version badhao** – `package.json` me `"version": "1.0.0"` → `"1.0.1"` (ya jaisa chaho).
|
|
14
|
+
2. Isi folder me terminal kholo:
|
|
15
|
+
```bash
|
|
16
|
+
cd "C:\xampp\htdocs\LRKmusics\easytube package published on npm"
|
|
17
|
+
npm login
|
|
18
|
+
npm publish
|
|
19
|
+
```
|
|
20
|
+
3. **Release build** lo – app ab npm se **lrkmusic-ytpro** load karegi.
|
|
21
|
+
|
|
22
|
+
## Package links
|
|
23
|
+
|
|
24
|
+
- npm: https://www.npmjs.com/package/lrkmusic-ytpro
|
|
25
|
+
- Settings: https://www.npmjs.com/settings/lrkassociations_mguide/packages
|
|
26
|
+
|
|
27
|
+
## Files (4)
|
|
28
|
+
|
|
29
|
+
- **script.js** – main logic (UI, Gemini, download, PIP, etc.)
|
|
30
|
+
- **bgplay.js** – background play (back/home par video band nahi hota – notification chalti rahti hai)
|
|
31
|
+
- **innertube.js** – innertube / player API
|
|
32
|
+
- **package.json** – name, version, main entry
|
|
33
|
+
|
|
34
|
+
## Feature: Back / Home par video band nahi
|
|
35
|
+
|
|
36
|
+
**bgplay.js** me: jab user watch/shorts se back karke home par aata hai, tab **Android.bgStop()** nahi bulaate. Isse notification aur background service chalte rahenge; band tab hi hoga jab YouTube screen close karenge ya notification se stop karenge.
|
package/bgplay.js
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/***** lrkmusic-ytpro bgplay *****
|
|
2
|
+
Author: Satya Prakash
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
if (typeof MediaMetadata === 'undefined') {
|
|
7
|
+
window.MediaMetadata = class {
|
|
8
|
+
constructor(data = {}) {
|
|
9
|
+
this.title = data.title || '';
|
|
10
|
+
this.artist = data.artist || '';
|
|
11
|
+
this.album = data.album || '';
|
|
12
|
+
this.artwork = data.artwork || [];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if (!('mediaSession' in navigator)) {
|
|
21
|
+
|
|
22
|
+
window.handlers = {};
|
|
23
|
+
window.serviceRunning=false;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
let _state = 'none';
|
|
29
|
+
let _metadata = null;
|
|
30
|
+
|
|
31
|
+
Object.defineProperty(navigator, 'mediaSession', {
|
|
32
|
+
value: {},
|
|
33
|
+
configurable: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
Object.defineProperty(navigator.mediaSession, 'metadata', {
|
|
37
|
+
get() {
|
|
38
|
+
return _metadata;
|
|
39
|
+
},
|
|
40
|
+
set(value) {
|
|
41
|
+
//console.log("metadata set:", value);
|
|
42
|
+
bgPlay(value);
|
|
43
|
+
_metadata = value;
|
|
44
|
+
},
|
|
45
|
+
configurable: true
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
navigator.mediaSession.setActionHandler = (action, handler) => {
|
|
52
|
+
|
|
53
|
+
if (typeof handler === 'function') {
|
|
54
|
+
handlers[action] = handler;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//console.log(action,handler)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
Object.defineProperty(navigator.mediaSession, 'playbackState', {
|
|
68
|
+
get() {
|
|
69
|
+
return _state;
|
|
70
|
+
},
|
|
71
|
+
set(value) {
|
|
72
|
+
|
|
73
|
+
//console.log("Custom playbackState set to:", value);
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
_state = value;
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
var ytproAud = getMediaElement();
|
|
80
|
+
|
|
81
|
+
if (value === 'playing' && ytproAud) {
|
|
82
|
+
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
83
|
+
} else if (value === 'paused' && (pauseAllowed || PIPause) && ytproAud) {
|
|
84
|
+
setTimeout(()=>{Android.bgPause(ytproAud.currentTime*1000);},100);
|
|
85
|
+
}
|
|
86
|
+
// Do NOT call bgStop() when user goes back to home – keep video running like YouTube app.
|
|
87
|
+
// Service stops only when YouTube screen is closed (app onDestroy) or user stops from notification.
|
|
88
|
+
// Removed: else if(value === "none" && !on watch/shorts){ Android.bgStop(); serviceRunning=false; }
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
},
|
|
93
|
+
configurable: true
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
} else {
|
|
99
|
+
window.handlers = window.handlers || {};
|
|
100
|
+
window.serviceRunning = window.serviceRunning || false;
|
|
101
|
+
try {
|
|
102
|
+
var origSet = navigator.mediaSession.setActionHandler;
|
|
103
|
+
if (origSet) {
|
|
104
|
+
navigator.mediaSession.setActionHandler = function(action, handler) {
|
|
105
|
+
if (typeof handler === 'function') window.handlers[action] = handler;
|
|
106
|
+
return origSet.call(navigator.mediaSession, action, handler);
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
var desc = Object.getOwnPropertyDescriptor(navigator.mediaSession, 'metadata');
|
|
110
|
+
if (desc && desc.set) {
|
|
111
|
+
var origMetaSet = desc.set;
|
|
112
|
+
Object.defineProperty(navigator.mediaSession, 'metadata', {
|
|
113
|
+
get: desc.get,
|
|
114
|
+
set: function(v) { origMetaSet.call(navigator.mediaSession, v); bgPlay(v); },
|
|
115
|
+
configurable: true, enumerable: desc.enumerable
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
} catch (e) {}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
function getMediaElement() {
|
|
128
|
+
var el = document.getElementsByClassName('video-stream')[0] || document.querySelector('video') || document.querySelector('audio');
|
|
129
|
+
return el || null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async function bgPlay(info){
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
if(!(window.location.href.indexOf("youtube.com/watch") > -1 || window.location.href.indexOf("youtube.com/shorts") > -1 || window.location.href.indexOf("music.youtube.com") > -1 )) return;
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
if(!info) return;
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
var ytproAud = getMediaElement();
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if(!ytproAud) return;
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
var iconBase64="iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
var img = new Image();
|
|
151
|
+
img.crossOrigin="anonymous";
|
|
152
|
+
img.src=info?.artwork?.[0]?.src;
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
var canvas = document.createElement('canvas');
|
|
156
|
+
canvas.style.width = "1600px";
|
|
157
|
+
canvas.style.height = "900px";
|
|
158
|
+
canvas.style.background="black";
|
|
159
|
+
var context = canvas.getContext('2d');
|
|
160
|
+
|
|
161
|
+
canvas.width = 160;
|
|
162
|
+
canvas.height = 90;
|
|
163
|
+
|
|
164
|
+
//var z=performance.now();
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
await new Promise((res,rej)=>{
|
|
168
|
+
img.onload=()=>res();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
try{
|
|
173
|
+
context.drawImage(img, 0,0 ,160,90);
|
|
174
|
+
iconBase64 = canvas.toDataURL('image/png',1.0);
|
|
175
|
+
}catch{}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
if(window.serviceRunning){
|
|
189
|
+
setTimeout(()=>{Android.bgUpdate(iconBase64.replace("data:image/png;base64,", ""),info.title,info.artist,ytproAud.duration*1000);},50);
|
|
190
|
+
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
191
|
+
}
|
|
192
|
+
else{
|
|
193
|
+
window.serviceRunning=true;
|
|
194
|
+
setTimeout(()=>{Android.bgStart(iconBase64.replace("data:image/png;base64,", ""),info.title,info.artist,ytproAud.duration*1000);},50);
|
|
195
|
+
setTimeout(()=>{Android.bgPlay(ytproAud.currentTime*1000);},100);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
/*When user hits the notification*/
|
|
228
|
+
function seekTo(t){
|
|
229
|
+
handlers.seekto({ seekTime: t/1000 });
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/*Daamm , its play*/
|
|
233
|
+
function playVideo(){
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
if(!pauseAllowed){
|
|
237
|
+
window.PIPause = false;
|
|
238
|
+
navigator.mediaSession.playbackState = 'playing';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
handlers.play();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/*Daamm , its pause*/
|
|
245
|
+
function pauseVideo(){
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if(!pauseAllowed){
|
|
250
|
+
window.PIPause=true;
|
|
251
|
+
navigator.mediaSession.playbackState = 'paused';
|
|
252
|
+
}
|
|
253
|
+
handlers.pause();
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
/*Alexa , play da next song*/
|
|
263
|
+
async function playNext(){
|
|
264
|
+
handlers.nexttrack();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
/*Alexa , play the f**ng song once again */
|
|
271
|
+
function playPrev(){
|
|
272
|
+
handlers.previoustrack();
|
|
273
|
+
}
|
package/innertube.js
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/***** lrkmusic-ytpro innertube *****
|
|
2
|
+
Author: Satya Prakash
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {BG} from 'https://youtube.com/ytpro_cdn/esm/bgutils-js@3.2.0/es2022/bgutils-js.bundle.mjs';
|
|
7
|
+
import "https://youtube.com/ytpro_cdn/esm/acorn@8.15.0/es2022/acorn.mjs";
|
|
8
|
+
import Jinter from 'https://youtube.com/ytpro_cdn/esm/jintr@3.3.1/es2022/jintr.bundle.mjs';
|
|
9
|
+
import {Player,Innertube, ProtoUtils, UniversalCache, Utils } from 'https://youtube.com/ytpro_cdn/npm/youtubei.js@13.4.0/bundle/browser.min.js';
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
function write(x){
|
|
14
|
+
|
|
15
|
+
if(typeof x == "object"){
|
|
16
|
+
x=JSON.stringify(x,null,2)
|
|
17
|
+
}
|
|
18
|
+
var ytproDownDiv=document.getElementById("downytprodiv");
|
|
19
|
+
|
|
20
|
+
ytproDownDiv.innerHTML=x;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
var cver="19.35.36";
|
|
28
|
+
var player_id;
|
|
29
|
+
var poToken,visitorData;
|
|
30
|
+
var sig_timestamp,nsig_sc,sig_sc;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
async function getPo(identifier){
|
|
39
|
+
const requestKey = 'O43z0dpjhgX20SCx4KAo';
|
|
40
|
+
|
|
41
|
+
const bgConfig = {
|
|
42
|
+
fetch: (input, init) => fetch(input, init),
|
|
43
|
+
globalObj: window,
|
|
44
|
+
requestKey,
|
|
45
|
+
identifier
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const bgChallenge = await BG.Challenge.create(bgConfig);
|
|
49
|
+
|
|
50
|
+
if (!bgChallenge)
|
|
51
|
+
throw new Error('Could not get challenge');
|
|
52
|
+
|
|
53
|
+
const interpreterJavascript = bgChallenge.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue;
|
|
54
|
+
|
|
55
|
+
if (interpreterJavascript) {
|
|
56
|
+
new Function(interpreterJavascript)();
|
|
57
|
+
} else throw new Error('Could not load VM');
|
|
58
|
+
|
|
59
|
+
const poTokenResult = await BG.PoToken.generate({
|
|
60
|
+
program: bgChallenge.program,
|
|
61
|
+
globalName: bgChallenge.globalName,
|
|
62
|
+
bgConfig
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return poTokenResult.poToken;
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
async function getDeciphers(){
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
return new Promise(async (resolve,reject)=>{
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
var scripts = document.getElementsByTagName('script');
|
|
84
|
+
for(var i=0;i<scripts.length;i++){
|
|
85
|
+
if(scripts[i].src.indexOf("/base.js") > 0){
|
|
86
|
+
player_id=scripts[i].src.match("(?<=player\/).*(?=\/player)");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
visitorData = ProtoUtils.encodeVisitorData(Utils.generateRandomString(11), Math.floor(Date.now() / 1000));
|
|
93
|
+
|
|
94
|
+
write("Fetching PoTokens...");
|
|
95
|
+
|
|
96
|
+
const coldStartToken = BG.PoToken.generatePlaceholder(visitorData);
|
|
97
|
+
await getPo(visitorData).then((webPo) => poToken = webPo);
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
write("Fetching Player JS...");
|
|
102
|
+
|
|
103
|
+
var player_js=await fetch(`https://www.youtube.com/s/player/${player_id}/player_ias.vflset/en_US/base.js`).then(x => x.text());
|
|
104
|
+
|
|
105
|
+
const ast = Jinter.parseScript(player_js, { ecmaVersion: 'latest', ranges: true });
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
sig_timestamp = Player.extractSigTimestamp(player_js);
|
|
110
|
+
const global_variable = Player.extractGlobalVariable(player_js, ast);
|
|
111
|
+
sig_sc = Player.extractSigSourceCode(player_js, global_variable);
|
|
112
|
+
nsig_sc = Player.extractNSigSourceCode(player_js, ast, global_variable);
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
//write(nsig_sc)
|
|
116
|
+
//write(sig_sc)
|
|
117
|
+
|
|
118
|
+
write("Deciphering Scripts...");
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
const player = await Player.fromSource(player_id, sig_timestamp, null, sig_sc, nsig_sc);
|
|
123
|
+
|
|
124
|
+
//write(JSON.stringify(player,null,2))
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
write("Deciphered Scripts")
|
|
130
|
+
|
|
131
|
+
resolve("done");
|
|
132
|
+
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
function decipherUrl(url){
|
|
157
|
+
|
|
158
|
+
const args = new URLSearchParams(url);
|
|
159
|
+
const url_components = new URL(args.get('url') || url);
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
if(args.get('s') != null){
|
|
164
|
+
const signature = Utils.Platform.shim.eval(sig_sc, {
|
|
165
|
+
sig: args.get('s')
|
|
166
|
+
});
|
|
167
|
+
const sp = args.get('sp');
|
|
168
|
+
if(sp) {
|
|
169
|
+
url_components.searchParams.set(sp, signature);
|
|
170
|
+
} else {
|
|
171
|
+
url_components.searchParams.set('signature', signature);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
const n = url_components.searchParams.get('n');
|
|
179
|
+
if(n != null){
|
|
180
|
+
var nsig = Utils.Platform.shim.eval(nsig_sc, {
|
|
181
|
+
nsig: n
|
|
182
|
+
});
|
|
183
|
+
url_components.searchParams.set('n', nsig);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
url_components.searchParams.set('pot',poToken);
|
|
188
|
+
url_components.searchParams.set('cver',cver);
|
|
189
|
+
return url_components.toString();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
window.getDownloadStreams=async ()=>{
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
write("Getting Deciphers...");
|
|
205
|
+
|
|
206
|
+
await getDeciphers();
|
|
207
|
+
|
|
208
|
+
write("Fethcing Video Info...");
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
var id="";
|
|
212
|
+
|
|
213
|
+
if(window.location.pathname.indexOf("shorts") > -1){
|
|
214
|
+
id=window.location.pathname.substr(8,window.location.pathname.length);
|
|
215
|
+
}
|
|
216
|
+
else{
|
|
217
|
+
id=new URLSearchParams(window.location.search).get("v");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
var body={
|
|
221
|
+
"videoId": id,
|
|
222
|
+
"racyCheckOk": true,
|
|
223
|
+
"contentCheckOk": true,
|
|
224
|
+
"playbackContext": {
|
|
225
|
+
"contentPlaybackContext": {
|
|
226
|
+
"vis": 0,
|
|
227
|
+
"splay": false,
|
|
228
|
+
"lactMilliseconds": "-1",
|
|
229
|
+
"signatureTimestamp": sig_timestamp
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"serviceIntegrityDimensions": {
|
|
233
|
+
"poToken": poToken
|
|
234
|
+
},
|
|
235
|
+
"context": {
|
|
236
|
+
"client": {
|
|
237
|
+
"hl": "en",
|
|
238
|
+
"gl": "US",
|
|
239
|
+
"remoteHost": "",
|
|
240
|
+
"screenDensityFloat": 1,
|
|
241
|
+
"screenHeightPoints": 7680,
|
|
242
|
+
"screenPixelDensity": 1,
|
|
243
|
+
"screenWidthPoints": 4320,
|
|
244
|
+
"visitorData": visitorData,
|
|
245
|
+
"clientName": "ANDROID",
|
|
246
|
+
"clientVersion": cver,
|
|
247
|
+
"osName": "Android",
|
|
248
|
+
"osVersion": "12",
|
|
249
|
+
"userAgent": "com.google.android.youtube/19.35.36(Linux; U; Android 13; en_US; SM-S908E Build/TP1A.220624.014) gzip",
|
|
250
|
+
//"platform": "DESKTOP",
|
|
251
|
+
"clientFormFactor": "UNKNOWN_FORM_FACTOR",
|
|
252
|
+
"userInterfaceTheme": "USER_INTERFACE_THEME_LIGHT",
|
|
253
|
+
"timeZone": "Asia/Calcutta",
|
|
254
|
+
"originalUrl": "https://www.youtube.com",
|
|
255
|
+
"deviceMake": "",
|
|
256
|
+
"deviceModel": "",
|
|
257
|
+
//"browserName": "Chrome",
|
|
258
|
+
//"browserVersion": "125.0.0.0",
|
|
259
|
+
"utcOffsetMinutes": 330,
|
|
260
|
+
"memoryTotalKbytes": "8000000",
|
|
261
|
+
/*"mainAppWebInfo": {
|
|
262
|
+
"graftUrl": "https://www.youtube.com",
|
|
263
|
+
"pwaInstallabilityStatus": "PWA_INSTALLABILITY_STATUS_UNKNOWN",
|
|
264
|
+
"webDisplayMode": "WEB_DISPLAY_MODE_BROWSER",
|
|
265
|
+
"isWebNativeShareAvailable": true
|
|
266
|
+
}*/
|
|
267
|
+
},
|
|
268
|
+
"user": {
|
|
269
|
+
"enableSafetyMode": false,
|
|
270
|
+
"lockedSafetyMode": false
|
|
271
|
+
},
|
|
272
|
+
"request": {
|
|
273
|
+
"useSsl": true,
|
|
274
|
+
"internalExperimentFlags": []
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
var info=await fetch("https://m.youtube.com/youtubei/v1/player?prettyPrint=false",{
|
|
283
|
+
method:"POST",
|
|
284
|
+
body:JSON.stringify(body)
|
|
285
|
+
}).then((res)=>res.json());
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
handleDownloadStreams(info);
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
function handleDownloadStreams(info){
|
|
301
|
+
console.log(info);
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
var ytproDownDiv=document.getElementById("downytprodiv");
|
|
307
|
+
|
|
308
|
+
var thumb=info?.videoDetails?.thumbnail?.thumbnails;
|
|
309
|
+
var vids=info?.streamingData?.formats;
|
|
310
|
+
var avids=info?.streamingData?.adaptiveFormats;
|
|
311
|
+
var cap=info?.captions?.playerCaptionsTracklistRenderer?.captionTracks;
|
|
312
|
+
var t=info?.videoDetails?.title.replaceAll("|","").replaceAll("\\","").replaceAll("?","").replaceAll("*","").replaceAll("<","").replaceAll("/","").replaceAll(":","").replaceAll('"',"").replaceAll(">","").replaceAll("'","");
|
|
313
|
+
ytproDownDiv.innerHTML=`<style>#downytprodiv a{text-decoration:none;} #downytprodiv li{list-style:none; display:flex;align-items:center;justify-content:center;border-radius:25px;padding:8px;background:${d};margin:5px;margin-top:8px}</style>`;
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
ytproDownDiv.innerHTML+="Select Available Formats<ul id='listurl'>";
|
|
318
|
+
|
|
319
|
+
for(var x in vids){
|
|
320
|
+
|
|
321
|
+
var url=vids[x].url;
|
|
322
|
+
|
|
323
|
+
ytproDownDiv.innerHTML+=`<li data-ytprotit="${t}" onclick="YTDownVid(this,'.mp4')" data-ytprourl="${url}">
|
|
324
|
+
${downBtn}<span style="margin-left:10px;" >${vids[x].qualityLabel} ${formatFileSize(((vids[x].bitrate*(vids[x].approxDurationMs/1000))/8))} </span></li>` ;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
ytproDownDiv.innerHTML+=`<li id="showAdaptives" onclick="showHideAdaptives()" style="min-height:20px;border-radius:5px">
|
|
329
|
+
Show Adaptive Formats (No Audio)
|
|
330
|
+
<span style="margin-left:10px;" >
|
|
331
|
+
<svg style="margin-top:5px" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="${c}" viewBox="0 0 18 18">
|
|
332
|
+
<path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708"/>
|
|
333
|
+
</svg>
|
|
334
|
+
</span>
|
|
335
|
+
</li>` ;
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
for(x in avids){
|
|
339
|
+
if(!(avids[x].mimeType.indexOf("audio") > -1)){
|
|
340
|
+
var url=avids[x].url;
|
|
341
|
+
ytproDownDiv.innerHTML+=`<li data-ytprotit="${t}" class="adpFormats" style="display:none;" onclick="YTDownVid(this,'.mp4')" data-ytprourl="${url}">
|
|
342
|
+
${downBtn}<span style="margin-left:10px;" >${avids[x].qualityLabel} ${formatFileSize(avids[x].contentLength)}
|
|
343
|
+
</span></li>` ;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
for(x in avids){
|
|
349
|
+
if(avids[x].mimeType.indexOf("audio") > -1){
|
|
350
|
+
var url=avids[x].url;
|
|
351
|
+
ytproDownDiv.innerHTML+=`<li data-ytprotit="${t}" onclick="YTDownVid(this,'.mp3')" data-ytprourl="${url}">
|
|
352
|
+
${downBtn}<span style="margin-left:10px;" >Audio ${avids[x]?.audioTrack?.displayName || ""} | ${avids[x].audioQuality.replace("AUDIO_QUALITY_","")}${formatFileSize(avids[x].contentLength)}
|
|
353
|
+
</span></li>` ;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
ytproDownDiv.innerHTML+="<br>Thumbnails<br><br><style>.thu{height:80px;border-radius:5px;}.thu img{max-height:97%;max-width:70%;border-radius:10px;border:1px solid silver;}</style>";
|
|
360
|
+
for(x in thumb){
|
|
361
|
+
ytproDownDiv.innerHTML+=`<li data-ytprotit="${t+Date.now()}" onclick="YTDownVid(this,'.png')" class="thu" data-ytprourl="${thumb[x].url}">
|
|
362
|
+
<img src="${thumb[x].url}"><br>
|
|
363
|
+
<span style="margin-left:30px;display:flex;align-items:center;justify-content:center;" >${downBtn}<span style="margin-left:10px;" >${thumb[x].height} ✕ ${thumb[x].width}
|
|
364
|
+
</span></span></li>` ;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if(cap && cap.length){
|
|
368
|
+
ytproDownDiv.innerHTML+=`<br>Captions<br><br><style>cp{width:100%;height:auto;padding-bottom:8px;}c{height:45px;width:50px;padding-top:5px;background:${d};border-radius:10px;margin-left:10px;display:block}</style>`;
|
|
369
|
+
for(var x in cap){
|
|
370
|
+
cap[x].baseUrl = cap[x].baseUrl.replace("&fmt=srv3","");
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
ytproDownDiv.innerHTML+=`<cp>
|
|
374
|
+
<span style="width:100px;text-align:left">${cap[x]?.name?.runs[0]?.text}</span>
|
|
375
|
+
<br><br>
|
|
376
|
+
<div style="position:absolute;right:10px;display:flex">
|
|
377
|
+
<c onclick="downCap('${cap[x].baseUrl}&fmt=sbv','${t}.txt')">${downBtn} <br>.txt</c>
|
|
378
|
+
<c onclick="downCap('${cap[x].baseUrl}&fmt=srt','${t}.srt')">${downBtn} <br>.srt</c>
|
|
379
|
+
<c onclick="downCap('${cap[x].baseUrl}','${t}.xml')" >${downBtn} <br>.xml</c>
|
|
380
|
+
<c onclick="downCap('${cap[x].baseUrl}&fmt=vtt','${t}.vtt')">${downBtn} <br>.vtt</c>
|
|
381
|
+
<c onclick="downCap('${cap[x].baseUrl}&fmt=srv1','${t}.srv1')">${downBtn} <br>.srv1</c><c onclick="downCap('${cap[x].baseUrl}&fmt=ttml','${t}.ttml')">${downBtn} <br>.ttml</c></div>
|
|
382
|
+
<br>
|
|
383
|
+
</cp>
|
|
384
|
+
<br><br>
|
|
385
|
+
<br><br>
|
|
386
|
+
`;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lrkmusic-ytpro",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "you can find the source code at",
|
|
5
|
+
"main": "script.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"republish": "npm version patch && npm publish"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "Satya Prakash",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"type": "commonjs",
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
}
|
|
17
|
+
}
|