Security News
The Push to Ban Ransom Payments Is Gaining Momentum
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
mp4frag
Advanced tools
Readme
A parser that reads piped data from ffmpeg containing a fragmented mp4 and splits it into an initialization segment and media segments. Designed for streaming live video relayed from cctv cameras.
You must use the correct output args with ffmpeg to create a compatible fragmented mp4 format similar to the following real world examples:
ffmpeg -loglevel quiet -rtsp_transport tcp -i rtsp://192.168.1.21:554/user=admin_password=pass_channel=0_stream=1.sdp?real_stream -reset_timestamps 1 -an -c:v copy -f mp4 -movflags +frag_every_frame+empty_moov+default_base_moof -min_frag_duration 500000 pipe:1
ffmpeg -loglevel quiet -rtsp_transport tcp -i rtsp://192.168.1.18:554/user=admin&password=pass&channel=1&stream=1.sdp -reset_timestamps 1 -an -c:v copy -f mp4 -movflags +frag_keyframe+empty_moov+default_base_moof pipe:1
count
parameter{ segment, sequence, duration, timestamp, keyframe }
keyframe >= 0
hlsBase
=> hlsPlaylistBase
string, accepts _
, a-z
, and A-Z
hlsSize
=> hlsPlaylistSize
integer, ranges from 2
to 20
, defaults to 4
hlsInit
=> hlsPlaylistInit
boolean, defaults to true
bufferListSize
=> segmentCount
integer, ranges from 2
to 30
, defaults to 2
mp4frag.on('segment', data => {
console.log(data);
});
{ segment, sequence, duration, timestamp }
hlsPlaylistBase
const mp4frag = new Mp4Frag({segmentCount: 3});
_
, a-z
, and A-Z
), setting this will generate a live fmp4 HLS m3u8 playlistconst mp4frag = new Mp4Frag({hlsPlaylistSize: 4, hlsPlaylistBase: 'my_String'});
const { spawn } = require('child_process');
const Mp4Frag = require('mp4frag');
const mp4frag = new Mp4Frag({hlsPlaylistSize: 3, hlsPlaylistBase: 'back_yard'});
const ffmpeg = spawn(
'ffmpeg',
['-loglevel', 'quiet', '-probesize', '64', '-analyzeduration', '100000', '-reorder_queue_size', '5', '-rtsp_transport', 'tcp', '-i', 'rtsp://216.4.116.29:554/axis-media/media.3gp', '-an', '-c:v', 'copy', '-f', 'mp4', '-movflags', '+frag_keyframe+empty_moov+default_base_moof', '-metadata', 'title="ip 216.4.116.29"', '-reset_timestamps', '1', 'pipe:1'],
{ stdio: ['ignore', 'pipe', 'inherit'] }
);
ffmpeg.stdio[1].pipe(mp4frag);
mp4frag.m3u8
and can be served to a client browser via expressmp4frag.getSegmentObject(6)
, with 6
being the current sequence number#EXTM3U
#EXT-X-VERSION:7
#EXT-X-ALLOW-CACHE:NO
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:6
#EXT-X-MAP:URI="init-back_yard.mp4"
#EXTINF:4.780000,
back_yard6.m4s
#EXTINF:5.439000,
back_yard7.m4s
#EXTINF:4.269000,
back_yard8.m4s
app.get('/back_yard.m3u8', (req, res) => {
if (mp4frag.m3u8) {
res.writeHead(200, {'Content-Type': 'application/vnd.apple.mpegurl'});
res.end(mp4frag.m3u8);
} else {
res.sendStatus(503);
}
});
app.get('/init-back_yard.mp4', (req, res) => {
if (mp4frag.initialization) {
res.writeHead(200, {'Content-Type': 'video/mp4'});
res.end(mp4frag.initialization);
} else {
res.sendStatus(503);
}
});
app.get('/back_yard:id.m4s', (req, res) => {
const segmentObject = mp4frag.getSegmentObject(req.params.id);
if (segmentObject) {
res.writeHead(200, {'Content-Type': 'video/mp4'});
res.end(segmentObject.segment);
} else {
res.sendStatus(503);
}
});
const { spawn } = require('child_process');
const Mp4Frag = require('mp4frag');
// 3 past segments will be held in memory for later access via mp4frag.segmentObjects
// if each segment has a duration of 2 seconds, then buffer will contain 6 seconds of video
const mp4frag = new Mp4Frag({segmentCount: 3});
const ffmpeg = spawn(
'ffmpeg',
['-loglevel', 'quiet', '-probesize', '64', '-analyzeduration', '100000', '-reorder_queue_size', '5', '-rtsp_transport', 'tcp', '-i', 'rtsp://131.95.3.162:554/axis-media/media.3gp', '-an', '-c:v', 'copy', '-f', 'mp4', '-movflags', '+frag_keyframe+empty_moov+default_base_moof', '-metadata', 'title="ip 131.95.3.162"', '-reset_timestamps', '1', 'pipe:1'],
{ stdio: ['ignore', 'pipe', 'inherit'] }
);
ffmpeg.stdio[1].pipe(mp4frag);
const fs = require('fs');
const { initialization, segmentObjects } = mp4frag;
if (initialization && segmentObjects) {
const fileName = `${Date.now()}.mp4`;
const writeStream = fs.createWriteStream(fileName);
// write the initialization fragment
writeStream.write(initialization);
// write the media segments
segmentObjects.forEach(({segment}) => {
writeStream.write(segment);
});
// end
writeStream.end();
}
FAQs
A parser that reads piped data from ffmpeg containing a fragmented mp4 and splits it into an initialization segment and media segments. Designed for streaming live video relayed from cctv cameras.
We found that mp4frag demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Ransomware costs victims an estimated $30 billion per year and has gotten so out of control that global support for banning payments is gaining momentum.
Application Security
New SEC disclosure rules aim to enforce timely cyber incident reporting, but fear of job loss and inadequate resources lead to significant underreporting.
Security News
The Python Software Foundation has secured a 5-year sponsorship from Fastly that supports PSF's activities and events, most notably the security and reliability of the Python Package Index (PyPI).