ffmpeg直播加水印、拉流等任务

 直播流加水印

ffmpeg -i  https://outbound-production.explore.org/stream-production-319/.m3u8  -vf "movie=black_water.png[watermark]; [in][watermark] overlay=main_w-overlay_w-20:main_h-overlay_h-10 [out]" -c:v libx264 -c:a copy -f flv "rtmp://livepush.gonature.cn/live/qwee?txSecret=39a51cfacc1d5d93216add5b5e0a017e&txTime=60DD7A3B"

 定时任务拉流并保存MP4文件

const ffmpeg = require('fluent-ffmpeg')
const config = require('./live_catch_tasks.json')
const fs = require('fs')
ffmpeg.setFfmpegPath('/usr/local/ffmpeg/bin/ffmpeg')  // /Users/bin/Downloads/ffmpeg 本机
const oneDay = 86400000
const tasks = {}  // 正在执行的任务
const checkAndRun = async function(){
  console.log('check and run task...', new Date())
  // 遍历任务列表
  for(let i in config.tasks){
    const task = config.tasks[i]
    const now = new Date()
    // 取当前时间,格式如 00:00 
    const time = ('0'+now.getHours()).slice(-2) + ':' + ('0'+now.getMinutes()).slice(-2)
    const exists = fs.existsSync(config.storeDir + task.saveAs)
    let overwrite = false
    if(exists){
      const filestat = fs.statSync(config.storeDir + task.saveAs) 
      // console.log('now:',now.getDay(),time,filestat.mtimeMs)
      if((now.getTime() - filestat.mtimeMs) > oneDay){
        overwrite = true
      }
    }
    // console.log(now.getDay() === task.weekDay,time >= task.startTime,(!exists || (exists && overwrite)))
    if(!tasks[task.name] && now.getDay() === task.weekDay  // 判断是否为当天任务
        && time >= task.startTime                          // 判断是否已到任务开始时间
        && (!exists || (exists && overwrite))){            // 判断文件是否已存在 或 上一次更新时间距现在是否大于24小时
      ((t)=> {
        tasks[t.name] = {
          id: t.id,
          name: t.name,
          saveAs: t.saveAs,
          status: null
        }
        // 创建 ffmpeg 任务
        tasks[t.name].process = ffmpeg(task.source)
          // .videoBitrate(1000)
          .addOptions(
            t.ffmpegOptions
          )
          .on('error', function(err, stdout, stderr) {
            console.error('record live error: ' + err.message)
            tasks[t.name].status = 'Error'
          })
          .on("start", function (commandLine) {
            console.log(commandLine) 
            tasks[t.name].status = 'Going'
          })
          .on("end", function () {
            // console.log('push over.') 
            delete tasks[t.name]
          })
          .save(config.storeDir + t.saveAs)
      })(task)
    }
  }
}
// 格式化输出到控制台
function log(){
  const list = Object.values(tasks).map(i=>{
    return { id: i.id, name: i.name, status: i.status || '', saveAs: i.saveAs}
  })
  list.sort((a,b)=> a.id - b.id )
  console.table(list)
}
function run(){
  checkAndRun()                    // 首次立即执行
  setInterval(checkAndRun, 30000)  // 每 30 秒检查一次
  setInterval(log, 5000)           // 日志每 5 秒输出一次
}
run()

/*
const cmd = ffmpeg('/Users/bin/Downloads/movies/心火/Firelight.1997.1080p.WEBRip.x264-RARBG.mp4')
// .duration(60)
// .loop(10)
// .seekInput(834.5) // set start time
.videoBitrate(1000)
// .noAudio()
.addOptions(
  [
    '-vcodec copy',
    '-acodec copy',
    '-bsf:a aac_adtstoasc'
  ]
)
// .output('/Users/bin/Downloads/outputfile.mp4')
// .output('rtmp://livepush.gonature.cn/live/live1?txSecret=d6f5ab25a7f845391b7b58dd274ef19e&txTime=858C3C88')
.on('error', function(err, stdout, stderr) {
  console.log('Cannot process video: ' + err.message);
})
.on('end', function() {
  console.log('Processing finished !');
})
.format("flv")
.output('rtmp://livepush.gonature.cn/live/live1?txSecret=d6f5ab25a7f845391b7b58dd274ef19e&txTime=858C3C88', {
  end: true
})
.on("start", function (commandLine) {
  console.log("pushing......") //开始推流
})
.on("error", function (err, stdout, stderr) {
  console.log('push error:', err) //推流失败
})
.on("end", function () {
  console.log('push over.') //推流结束
});

cmd.run();
//.save('/Users/bin/Downloads/outputfile.mp4');
*/

node方式拉流推流并加水印

 var ffmpeg = require('fluent-ffmpeg');
 const command = ffmpeg('https://outbound-production.explore.org/stream-production-319/.m3u8')
    .videoFilters("movie=black_water.png[watermark]; [in][watermark] overlay=main_w-overlay_w-20:main_h-overlay_h-10 [out]")
    .addOptions([
      "-vcodec libx264",
      "-preset ultrafast",
      "-acodec aac"
    ])
    .format("flv")
    .output('rtmp://livepush.gonature.cn/live/qwee?txSecret=39a51cfacc1d5d93216add5b5e0a017e&txTime=60DD7A3B', {
      end: true
    })
    .on("start", function (commandLine) {
      console.log("commandLine: " + commandLine);
    })
    .on("error", function (err, stdout, stderr) {
		 console.log("commandLine: " + '失败');
    })
    .on("end", function () {
      
    });
  command.run()

使用process_argv传递参数,执行固定的ID之间的任务

启动方式:

node manage.js 1 3
任务id 1-3,包含1和3

const ffmpeg = require('fluent-ffmpeg')
const config = require('./live_push_tasks.json')
const fs = require('fs')
// ffmpeg.setFfmpegPath('/usr/local/ffmpeg/bin/ffmpeg')  // /Users/bin/Downloads/ffmpeg 本机
const oneDay = 86400000
const tasks = {}  // 正在执行的任务
let begin = 1 // 开始初始值
let end = 100 // 结束初始值
process.argv.forEach(function(val, index, array) {
    console.log(index + ': ' + val);
    if (index === 2) {
        begin = val
    }
    if (index === 3) {
        end = val
    }
});
const checkAndRun = async function(){
    console.log('check and run task...', new Date())
    // 遍历任务列表
    for(let i in config.tasks){
        const task = config.tasks[i]
        const now = new Date()
        // console.log(now.getDay() === task.weekDay,time >= task.startTime,(!exists || (exists && overwrite)))
        if(!tasks[task.name] && begin <=task.id && end>=task.id){            // 判断文件是否已存在 或 上一次更新时间距现在是否大于24小时
            ((t)=> {
                tasks[t.name] = {
                    id: t.id,
                    name: t.name,
                    saveAs: t.saveAs,
                    status: null
                }
                // 创建 ffmpeg 任务
                tasks[t.name].process = ffmpeg('https://outbound-production.explore.org/stream-production-'+task.source+'/.m3u8')
                    .videoFilters("movie=black_water.png[watermark]; [in][watermark] overlay=main_w-overlay_w-20:main_h-overlay_h-10 [out]")
                    .addOptions([
                        "-vcodec libx264",
                        "-preset ultrafast",
                        "-acodec aac"
                    ])
                    .format("flv")
                    .output(task.output, {
                        end: true
                    })
                    .on("start", function (commandLine) {
                        console.log(commandLine)
                        tasks[t.name].status = 'Going'
                    })
                    .on("error", function (err, stdout, stderr) {
                        console.error('record live error: ' + err.message)
                        tasks[t.name].status = 'Error'
                    })
                    .on("end", function () {
                        delete tasks[t.name]
                    }).run();
            })(task)
        }
    }
}
// 格式化输出到控制台
function log(){
    const list = Object.values(tasks).map(i=>{
        return { id: i.id, name: i.name, status: i.status || ''}
    })
    list.sort((a,b)=> a.id - b.id )
    console.table(list)
}
function run(){
    checkAndRun()                    // 首次立即执行
    setInterval(checkAndRun, 30000)  // 每 30 秒检查一次
    setInterval(log, 5000)           // 日志每 5 秒输出一次
}
run()

添加码率

const ffmpeg = require('fluent-ffmpeg')
const config = require('./live_push_tasks.json')
const fs = require('fs')
// ffmpeg.setFfmpegPath('/usr/local/ffmpeg/bin/ffmpeg')  // /Users/bin/Downloads/ffmpeg 本机
const oneDay = 86400000
const tasks = {}  // 正在执行的任务
let begin = 1 // 开始初始值
let end = 100 // 结束初始值
process.argv.forEach(function(val, index, array) {
    console.log(index + ': ' + val);
    if (index === 2) {
        begin = val
    }
    if (index === 3) {
        end = val
    }
});
const checkAndRun = async function(){
    console.log('check and run task...', new Date())
    // 遍历任务列表
    for(let i in config.tasks){
        const task = config.tasks[i]
        const now = new Date()
        // console.log(now.getDay() === task.weekDay,time >= task.startTime,(!exists || (exists && overwrite)))
        if(!tasks[task.name] && begin <=task.id && end>=task.id){            // 判断文件是否已存在 或 上一次更新时间距现在是否大于24小时
            ((t)=> {
                tasks[t.name] = {
                    id: t.id,
                    name: t.name,
                    saveAs: t.saveAs,
                    status: null
                }
                // 创建 ffmpeg 任务
                tasks[t.name].process = ffmpeg('https://outbound-production.explore.org/stream-production-'+task.source+'/.m3u8')
                    .videoFilters("movie=black_water.png[watermark]; [in][watermark] overlay=main_w-overlay_w-20:main_h-overlay_h-10 [out]")
                    .addOptions([
                        "-vcodec libx264",
                        "-preset ultrafast",
                        "-acodec aac",
                        "-video_size 1920x1080"
                    ])
                    .videoBitrate('3072k')
                    .format("flv")
                    .output(task.output, {
                        end: true
                    })
                    .on("start", function (commandLine) {
                        console.log(commandLine)
                        tasks[t.name].status = 'Going'
                    })
                    .on("error", function (err, stdout, stderr) {
                        console.error('record live error: ' + err.message)
                        tasks[t.name].status = 'Error'
                    })
                    .on("end", function () {
                        delete tasks[t.name]
                    }).run();
            })(task)
        }
    }
}
// 格式化输出到控制台
function log(){
    const list = Object.values(tasks).map(i=>{
        return { id: i.id, name: i.name, status: i.status || ''}
    })
    list.sort((a,b)=> a.id - b.id )
    console.table(list)
}
function run(){
    checkAndRun()                    // 首次立即执行
    setInterval(checkAndRun, 30000)  // 每 30 秒检查一次
    setInterval(log, 5000)           // 日志每 5 秒输出一次
}
run()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值