使用 Nodejs + FFmpeg 实现的直播推流第二弹

▲ 视频作者 LiarOnce (http://www.bilibili.com/video/av9852916/

人生不止眼前的苟且,还有装逼和浪。——香菇夫斯基

故事起源于《作为程序猿(装逼汪),要不要试试用代码推流到B站直播?》,这里只是代码的升级优化,所以没什么好说的。

优化内容

  • 将函数递归调用实现的“循环推流”改成 pm2 实现的“进程守护”,从而实现进程结束自动重启、意外终结自动重启、后台管理、日志记录等功能;
  • 改写参数实现添加水印
  • 顺序播放改为随机播放

新的问题

  • B站直播修改了网页端播放器,导致断流重推后直播卡住,需要刷新才能续看。(目前与 一心月 交换了新的意见,待测试。

本次需要准备的环境和三方模块(纯净环境下

  • node.js 环境(某菇在B站发的唯一一个视频中讲到过)
  • pm2(Node模块:本次主角,用于守护进程)
  • fluent-ffmpeg(Node模块:封装了ffmpeg的api)
  • silly-datetime(Node模块:格式化时间,用于日志记录)
  • ffmpeg(用于支持推流)
  • 可以正常联网的计算机(PC、MAC、Linux、Raspberry Pi、……)

代码

var fs = require('fs');  //文件操作模块
var sd = require('silly-datetime');  //时间格式化模块
var D = './video2/';  //存放视频文件的目录
var L = './pic/tips2.png';  //水印
var R = 'rtmp://txy.live-send.acg.tv/live-txy/';  //推流地址
var C = '?streamname=live_4669771_4358269&key=a387ef5965ce24df5512345e727e89da';  //推流参数
var O = '';  //测试输出,一般填写“文件名+.格式”的形式,留空则不启用

function showTime() {
  return sd.format(new Date(), 'YYYY-MM-DD HH:mm');
}

function liveON() {
 var V = fs.readdirSync(D);
  var N = V.length;
 var ID = Math.floor(Math.random() * N);
 var ffmpeg = require('fluent-ffmpeg');
  var inputPath = D + V[ID];
  var outputPath = O == '' ? (R + C) : O;
 console.log('[' + showTime() + '] Find ' + N + ' Video Files !');
 ffmpeg(inputPath)
   .inputOptions('-re')
    .inputOptions('-ac 2')
    .addInput(L)
    .complexFilter([{
     filter: 'scale',
      options: [1280, -1],
      inputs: '[0:v]',
      outputs: 'video'
    }, {
      filter: 'scale',
      options: [220, -1],
     inputs: '[1:v]',
      outputs: 'logo'
   }, {
      filter: 'overlay',
      options: {
        x: 'main_w-overlay_w-15',
       y: 15
     },
      inputs: ['video', 'logo']
   }])
   .on('start', function(commandLine) {
      //console.log('Spawned Ffmpeg with command: ' + commandLine);
     console.log('[' + showTime() + '] Vedio "' + V[ID] + '" is Pushing !');
     console.log('[' + showTime() + '] Spawned Ffmpeg with command !');
    })
    .on('error', function(err, stdout, stderr) {
      console.log('error: ' + err.message);
     console.log('stdout: ' + stdout);
     console.log('stderr: ' + stderr);
   })
    .on('end', function() {
     console.log('[' + showTime() + '] Vedio "' + V[ID] + '" Pushing is Finished !');
    })
    .addOptions([
     '-vcodec libx264',
      '-preset veryfast',
     '-crf 22',
      '-maxrate 1000k',//1000k
      '-bufsize 3000k',
     '-acodec libmp3lame',
     '-ac 2',
      '-ar 44100',
      '-b:a 96k'
    ])
    .format('flv')
    .output(outputPath, {
     end: true
   })
    .run();
}

liveON();

截至目前发文,香菇已经把该代码放在腾讯云运行超过48小时,期间直播未间断:http://live.bilibili.com/64285

(待续)

标签: none

已有 36 条评论

  1. 学习了!!!!

  2. 围观大佬,美国vps推流起来会比较蛋疼吧- -没有国内主机
    pm2是个好东西,我用来守护ghost进程的

    1. 有些平台有国外线路的所以带宽问题应该不大,主要看配置够不够,我测试用的腾讯云(1C1G1M)推起来就卡卡的⊙ω⊙

      1. 美国的带宽虽说比较大,但是我配置比你还低,看来带不动了
        弱弱问问大佬,你一天要推多少g流量?

        1. 估算一下大概每天10G左右,每分钟七八兆的样子。

  3. .这弹幕。。。略微影响阅读呀。。然后很混乱,其实可以做在内页,显示当前文章的弹幕。。

    1. 哈哈哈哈哈是啊目前只实现了功能,更多细节有待优化,嗯!

      1. WeDo WeDo

        可以加一个弹幕开关会比较友好哦

        1. 哈依哈依~在完善版本中会有的

  4. 诶卧槽 这弹幕什么鬼qwq

    1. 普通的弹幕啊233

  5. 于是我就闲得胃疼录了波视频(录着录着电脑卡出翔了)

    1. 咦?录了什么视频~

      1. 你不介意前面几秒就行:av9852916

        1. 赛高!视频采用~嘿嘿嘿(●ˇ∀ˇ●)

评论已关闭