rtsp/rtmp转m3u8 nodejs+ffmpeg实现

本文使用node.js和ffmpeg实现了rtsp/rtmp直播流转m3u8

核心代码

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
const ffmpegPath = require('@ffmpeg-installer/ffmpeg')
const ffmpeg = require('fluent-ffmpeg')
const fs = require('fs')
const path = require('path')
const http = require('http')

ffmpeg.setFfmpegPath(ffmpegPath.path)

main()

function main () {
const rtsp = 'rtmp://192.168.31.249:1935/live/test'
const m3u8 = './m3u8/live.m3u8'
transcoding(rtsp, m3u8)
createServer(7777)
}

function transcoding (rtsp, m3u8) {
ffmpeg(rtsp)
.outputOptions([
'-fflags flush_packets',
'-max_delay 1',
'-an',
'-flags',
'-global_header',
'-hls_time 1',
'-hls_list_size 3',
'-hls_wrap 3',
'-vcodec copy'
])
.on('start', function(e) {
console.log('---开始转码---')
console.log(e);
})
.on('end', function() {
console.log('file has been converted succesfully');
})
.on('error', function(err) {
console.log('an error happened: ' + err.message);
fun('error')
})
.save(m3u8)
}

function createServer (port) {
const mimes = {
'ts': 'video/MP2T',
'm3u8': 'application/x-mpegURL'
}
const liveServer = http.createServer((request, response) => {
const urlArrs = request.url.split('.')
const extension = urlArrs[urlArrs.length - 1]
if (extension === 'ts') {
try {
response.setHeader('Content-Type', mimes['ts'])
fs.createReadStream(path.join('./m3u8', request.url)).pipe(response)
} catch (error) {
response.end('hello world')
}
} else if (extension === 'm3u8') {
try {
response.setHeader('Content-Type', mimes['m3u8'])
fs.createReadStream(path.join('./m3u8', request.url)).setEncoding('utf8').pipe(response)
} catch (error) {
response.end('hello world')
}
} else if (extension === 'html') {
try {
fs.createReadStream(path.join('./', request.url)).setEncoding('utf8').pipe(response)
} catch (error) {
response.end('hello world')
}
} else {
response.end('hello world')
}
})

liveServer.listen(port, err => {
console.log(err)
console.log(`liveServer run ${port}`)
})
}
  • fluent-ffmpeg是ffmpeg的nodejs实现。你也可以使用child_process直接调用ffmpeg命令,原理是一样的。
  • @ffmpeg-installer/ffmpeg是一个ffmpeg安装器,可以根据当前系统安装对应的可执行文件。这里指定了ffmpeg的路径使用项目中下载好的。如果不指定会使用系统安装好的ffmpeg
  • fluent-ffmpeg会把参数转化为ffmpeg命令,ffmpeg -i rtmp://192.168.31.249:1935/live/test -y -fflags flush_packets -max_delay 1 -an -flags -global_header -hls_time 1 -hls_list_size 3 -hls_wrap 3 -vcodec copy ./m3u8/live.m3u8

demo源码:https://github.com/blogwy/personal-practice/tree/master/rtsp-to-m3u8