-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathm3ucheck.js
152 lines (129 loc) · 4.9 KB
/
m3ucheck.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
const { spawn, exec } = require('child_process');
const fs = require('fs');
const { setTimeout } = require('timers/promises');
const m3uFilePath = 'file.m3u'; // Replace with your M3U file path
const vlcTimeout = 10000; // 10 seconds timeout for VLC to start playing the stream
const resultFilePath = 'stream_results.txt';
// Array to hold references to all spawned VLC processes
let vlcProcesses = [];
function parseM3U(m3uContent) {
let lines = m3uContent.split('\n');
let streams = [];
let currentStream = {};
lines.forEach(line => {
line = line.trim();
if (line.startsWith('#EXTINF:')) {
let info = line.substring(8).trim();
currentStream.name = info.split(',')[1] || ''; // Get channel name from #EXTINF
} else if (line.startsWith('#EXTVLCOPT:http-referrer=')) {
currentStream.referrer = line.substring(24).trim();
} else if (line.startsWith('#EXTVLCOPT:http-user-agent=')) {
currentStream.userAgent = line.substring(25).trim();
} else if (line.startsWith('http')) {
currentStream.url = line.trim();
streams.push(currentStream);
currentStream = {};
}
});
return streams;
}
async function checkStream(stream) {
let vlcCommand = `vlc --intf dummy --no-video --play-and-exit "${stream.url}"`;
let vlcProcess = spawn(vlcCommand, [], { shell: true });
vlcProcesses.push({ pid: vlcProcess.pid, process: vlcProcess }); // Store PID and reference to the VLC process
let timeoutPromise = setTimeout(vlcTimeout);
let hasError = false;
vlcProcess.stdout.on('data', (data) => {
let output = data.toString();
if (output.includes('main input error')) {
hasError = true;
}
});
vlcProcess.stderr.on('data', (data) => {
let output = data.toString();
if (output.includes('cannot open') || output.includes('main input error')) {
hasError = true;
}
});
try {
await Promise.race([timeoutPromise]);
if (!hasError) {
console.log(`${stream.name} - working`);
appendResult(`${stream.name} - working`);
} else {
console.log(`${stream.name} - failed to start playback`);
appendResult(`${stream.name} - failed to start playback`);
}
} catch (err) {
console.error(`${stream.name} - failed (error: ${err.message})`);
appendResult(`${stream.name} - failed (error: ${err.message})`);
} finally {
// Kill the VLC process
killVLCProcess(vlcProcess.pid);
}
}
function appendResult(result) {
fs.appendFileSync(resultFilePath, result + '\n', (err) => {
if (err) {
console.error('Error appending to stream_results.txt:', err);
}
});
}
function killVLCProcess(pid) {
console.log(`Killing VLC process with PID ${pid}`);
if (process.platform === 'win32') {
// Windows-specific termination
exec(`taskkill /pid ${pid} /f /t`, (err, stdout, stderr) => {
if (err) {
console.error(`Error killing process ${pid}: ${err}`);
}
});
} else {
// Linux and other Unix-like OS
process.kill(pid, 'SIGKILL');
}
}
// Check if the result file exists and delete it if it does
fs.access(resultFilePath, fs.constants.F_OK, (err) => {
if (!err) {
// File exists, so delete it
fs.unlink(resultFilePath, (err) => {
if (err) {
console.error('Error deleting existing stream_results.txt:', err);
}
});
}
});
fs.readFile(m3uFilePath, 'utf8', async (err, data) => {
if (err) {
console.error(`Error reading file: ${err}`);
return;
}
const streams = parseM3U(data);
for (let stream of streams) {
if (!stream.name) {
stream.name = stream.url.split('/').pop().split('.')[0]; // Use filename as fallback name
}
await checkStream(stream);
}
console.log('All streams checked.');
// Kill all VLC processes at the end of script execution
killVLCProcesses();
process.exit(0); // Ensure script terminates after all streams are checked
});
function killVLCProcesses() {
vlcProcesses.forEach(vlcProcess => {
console.log(`Killing VLC process with PID ${vlcProcess.pid}`);
if (process.platform === 'win32') {
// Windows-specific termination
exec(`taskkill /pid ${vlcProcess.pid} /f /t`, (err, stdout, stderr) => {
if (err) {
console.error(`Error killing process ${vlcProcess.pid}: ${err}`);
}
});
} else {
// Linux and other Unix-like OS
process.kill(vlcProcess.pid, 'SIGKILL');
}
});
}