|
var fs = require ('fs'), |
|
cp = require ('child_process'), |
|
u = require ('util'), |
|
sq = require ('sequence').Sequence; |
|
|
|
(function (undefined) { |
|
'use strict'; |
|
if (typeof window != 'undefined' || typeof require != 'function') |
|
// Not node js :< |
|
throw new TypeError('You should run this script under NodeJS: http://nodejs.org/'); |
|
|
|
process.stdout.write ('Parse command line... '); |
|
// Parse command line |
|
for (var i=2, curFlag, __FLAG__ = {}; i<process.argv.length; i++) { |
|
if (!process.argv[i].indexOf ('--')) { |
|
// Begin with -- |
|
// Which sets the current flag value. |
|
curFlag = process.argv[i].slice(2); |
|
__FLAG__[curFlag] = []; |
|
} else if (curFlag && __FLAG__[curFlag]) { |
|
__FLAG__[curFlag].push (process.argv[i]); |
|
} |
|
} |
|
for (var x in __FLAG__) __FLAG__[x] = __FLAG__[x].join(' '); |
|
|
|
var hasFlag = function (flag) { return __FLAG__[flag] !== undefined; }, |
|
_ = function (fooo) { return fooo.toString().match(/\/\*\s?([\s\S]+)\s*\*\//)[1]; }; |
|
|
|
process.stdout.write ('Checking flags... '); |
|
|
|
// If is not windows and avconv flag not specified, set avconv to true. |
|
if (process.platform.indexOf('win') && !hasFlag('avconv')) |
|
__FLAG__.avconv = 1; |
|
|
|
var ffmpeg = __FLAG__.avconv ? 'avconv' : 'ffmpeg', |
|
isDebug = hasFlag ('verbose'); |
|
|
|
var sprintf = function () { |
|
var ret = u.format.apply(this, arguments); |
|
if (isDebug) console.log ('> %s', ret); |
|
return ret; |
|
}; |
|
|
|
if (hasFlag('help')) { |
|
process.stdout.write('\r'); |
|
console.log(_(function () {/* |
|
# Sina FLV Blacker for node ver 1.0 By Jixun # |
|
Should work under windows, not tested. |
|
|
|
Ported from FlvPatcher by Dant[http://danknest.org] |
|
> https://github.com/dantmnf/FlvPatcher/blob/master/blacker.sh |
|
|
|
## Usage: |
|
> nodejs [script] [--options] --input <Source file> --output [Output path] |
|
|
|
## Extra: |
|
--overwrite |
|
Overwrite exist file contents. |
|
|
|
--avconv <1/0> |
|
Uses avconv instead of ffmpeg to encode video, default true for linux |
|
|
|
--verbose |
|
Print console output after each command. |
|
|
|
--mediainfo |
|
Execute mediainfo after finish. |
|
|
|
## FAQ: |
|
Command not found errors |
|
> Ubuntu based: sudo apt-get install ffmpeg ffmsindex mkvtoolnix mediainfo |
|
> Windows: Just place the exe here. |
|
> Other: Install its binarys. |
|
*/}).replace('[script]', process.argv[1].replace(/.+(\/|\\)/, ''))); |
|
process.exit (0); |
|
} |
|
|
|
if (!__FLAG__.input || !fs.existsSync(__FLAG__.input)) { |
|
console.error ("Input argument missing or the file doesn\'t exist, exit (1)."); |
|
process.exit (1); |
|
} |
|
var inputPath = __FLAG__.input; |
|
|
|
|
|
// Measure file size |
|
var inputFileSize = fs.statSync(inputPath).size; |
|
if (!inputFileSize) { |
|
console.error ("Input file size is 0, exit (3)"); |
|
process.exit (3); |
|
} |
|
|
|
|
|
if (!__FLAG__.output) __FLAG__.output = inputPath.replace(/\.[^.]+$/, '') + '.buggy.flv'; |
|
if (fs.existsSync(__FLAG__.output) && !hasFlag('overwrite')) { |
|
console.error ("Output exists without --overwrite flag specified, exit (2)."); |
|
process.exit (2); |
|
} |
|
var outputPath = __FLAG__.output; |
|
|
|
var targetBitrate = parseInt (__FLAG__.bitrate); |
|
if (targetBitrate <= 0 || targetBitrate > 1000 || !targetBitrate) { |
|
targetBitrate = 740; |
|
console.log ('Invalid target bitrate, changed to %s.', targetBitrate); |
|
} |
|
|
|
console.log ('Ready.'); |
|
|
|
// Generate temp file name. |
|
var tmpFile = (__FLAG__.tmp || '.') + '/.tmp-' + (+new Date()) + '-' + Math.random(), |
|
tmpPatch = tmpFile + 'patch.mkv', |
|
tmpJoin = tmpFile + 'joined.mkv', |
|
tmpTC = tmpFile + '_track00.tc.txt'; |
|
|
|
console.log ('Exporting tc file to %s ...', tmpTC); |
|
|
|
sq.create().then(function (next) { |
|
console.log ('Generate time code ...'); |
|
cp.exec (sprintf('ffmsindex -c "%s" "%s"', inputPath, tmpFile), next); |
|
}).then(function (next, error, stdout, stderr) { |
|
if (isDebug) console.log (stderr || stdout || '> Nothing coming out'); |
|
console.log ('Generate black patch ...'); |
|
cp.exec (sprintf('%s -i "%s" -c copy -frames:v 3 -- "%s"', ffmpeg, inputPath, tmpPatch), next); |
|
}).then(function (next, error, stdout, stderr) { |
|
if (isDebug) console.log (stderr || stdout || '> Nothing coming out'); |
|
var hFile = fs.openSync (tmpTC, 'a'); |
|
var appendBlackTime = function (strToWrite) { |
|
var buf = new Buffer(strToWrite + '\n'); |
|
fs.writeSync (hFile, buf, 0, buf.length); |
|
}; |
|
// 这里的计算和原版有少许不同的样子… 不过大致还是正确的。 |
|
var blackTime = (( (inputFileSize + fs.statSync(tmpPatch).size) / targetBitrate ) * 8000).toFixed(8); |
|
|
|
console.log ('Black time: %s', blackTime); |
|
|
|
for (var i=0; i<3; i++) |
|
appendBlackTime (blackTime + i * 60); |
|
|
|
fs.close(hFile, next); |
|
}).then(function (next, error, stdout, stderr) { |
|
if (isDebug) console.log (stderr || stdout || '> Nothing coming out'); |
|
console.log ('Join the old video and new one ...'); |
|
cp.exec (sprintf('mkvmerge -o "%s" --timecodes "0:%s" \\( "%s" \\) + \\( "%s" \\) --track-order "0:0,0:1"', |
|
tmpJoin, tmpTC, inputPath, tmpPatch |
|
), next); |
|
}).then(function (next, error, stdout, stderr) { |
|
if (isDebug) console.log (stderr || stdout || '> Nothing coming out'); |
|
console.log ('Convert to flv ...'); |
|
cp.exec (sprintf('%s -f matroska -i "%s" -c copy -f flv -y -- "%s"', ffmpeg, tmpJoin, outputPath), next); |
|
}).then(function (next, error, stdout, stderr) { |
|
if (isDebug) console.log (stderr || stdout || '> Nothing coming out'); |
|
process.stdout.write ('Clean up... '); |
|
[tmpFile, tmpJoin, tmpPatch, tmpTC].forEach(fs.unlinkSync); |
|
console.log ('done.'); |
|
if (hasFlag('mediainfo')) { |
|
console.log (); |
|
cp.exec(sprintf('mediainfo %s', outputPath), function (error, stdout, stderr) { |
|
var mediainfo = stderr || stdout || '> Nothing coming out'; |
|
if (isDebug) { |
|
console.log (mediainfo); |
|
} else { |
|
console.log (mediainfo.match(/.+bit\s*rate.*/)[0]); |
|
} |
|
process.exit (0); |
|
}); |
|
} else { |
|
process.exit (0); |
|
} |
|
}); |
|
})(); |