Skip to content

Instantly share code, notes, and snippets.

@mashihua
Last active July 2, 2016 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mashihua/1e45c823e12a368ee414cafc892a7b64 to your computer and use it in GitHub Desktop.
Save mashihua/1e45c823e12a368ee414cafc892a7b64 to your computer and use it in GitHub Desktop.
for video codec check
#!/usr/bin/env node
const path = require('path')
const http = require('http')
const https = require('https')
const spawn = require('child_process').spawn;
const fs = require('fs');
const os = require('fs');
function path_resove(uri, file){
return path.dirname(uri) + '/' + file
}
function pase_m3u8(uri, format){
var prot = /^http/.test(uri) ? http:
/^https/.test(uri) ? https :
null
if(!prot){
return Promise.reject(new Error('Does not support this protocol.'))
}
return new Promise(function(resolve, reject){
prot.get(uri, function(res){
res.resume();
if(res.statusCode !== 200){
return reject(new Error('Resource not found.'))
}
var data = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
data += chunk
});
res.on('end', function(){
var s = data.match(/^.+\.ts$/mg)
if(s && s.length){
return resolve(path_resove(uri,s[0]))
}
reject(new Error('Resource not found.'))
});
}).on('error', (e) => {
reject(e)
})
});
}
function parse(data){
var arr = data.split(/\[\/STREAM\]/g);
var item = {
audio: {},
video: {}
}
if(!arr && arr.length){
return null;
}
for(var i = 0; i < 2; i++){
var n = arr[i];
if(/channels/.test(n)){
item.audio.channels = /^channels=(.+)$/mg.exec(n)[1]
item.audio.codec_name = /^codec_name=(.+)$/mg.exec(n)[1]
item.audio.profile = /^profile=(.+)$/mg.exec(n)[1]
item.audio.sample_rate = /^sample_rate=(.+)$/mg.exec(n)[1]
}else{
item.video.codec_name = /^codec_name=(.+)$/mg.exec(n)[1]
item.video.profile = /^profile=(.+)$/mg.exec(n)[1]
item.video.level = /^level=(.+)$/mg.exec(n)[1]
}
}
return item;
}
function exec(file){
file = file.trim();
return new Promise(function(resolve, reject){
if(/\.m3u8$/.test(file)){
return pase_m3u8(file)
.then(function(result){
exec(result).then(function(item){
resolve(item)
})
})
}
if(!file.match(/http[s]?/) && !fs.existsSync(file)){
return reject(new Error('File does not exist'));
}
var proc = os.platform === 'win32' ? 'ffprobe.exe' : 'ffprobe';
var ffprobe = spawn(proc, ['-show_streams', file]);
ffprobe.on('error', function(err){
return reject(err);
});
var result = '';
ffprobe.stdout.on('data', function(data){
result += data;
});
ffprobe.on('close', function(code){
if(code !== 0){
return reject(new Error('Exec ffprobe error, exit code: ' + code));
}else{
resolve(parse(result))
}
})
})
}
function audio_code(item){
// need to see ietf document
if(item.audio.codec_name === 'aac'){
return 'mp4a.40.2'
}
var codec_name = ['aac', '']
var profile = ['LC']
}
function video_code(item){
var codec_names = {h264: 'avc1'}
var profiles = {Baseline :66, Main : 77, High : 100}
var exts = {Baseline: 'E0', Main: '40', High: '00'}
var res = [];
var res1 = []
var code_name = item.video.codec_name
, profile = item.video.profile
, level = item.video.level;
if(code_name === 'h264'){
res.push(codec_names[code_name])
res.push('.')
res1.push(codec_names[code_name])
profile = profiles[profile]
var p = profile && parseInt(profile)
res.push(p.toString(16))
res1.push(p)
res.push(exts[item.video.profile])
level = parseInt(level)
res.push(level.toString(16))
res1.push(level)
}
return [res1.join('.'),res.join('')]
}
if(process.argv.length < 3){
return console.log('node codec_check.js <file or url>')
}
process.argv.slice(2).forEach(function(file){
exec(file).then(function(result){
var a = audio_code(result)
var v = video_code(result)
result.codec = []
for(var i = 0 ; i < v.length; i++){
result.codec.push(v[i] + ', ' + a)
}
console.log(file)
console.dir(result)
}).catch(function(err){
console.error(err);
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment