What I want to achieve is to take screenshots continuously and pass them to nodejs application in order to process each one separately and do some other stuff. I need this for Linux environment only. I picked ffmpeg
with x11grab
as a screenshots provider. The following command works just fine:
ffmpeg -t 10 -s 1366x768 -f x11grab -i :0.0+0,0 -vf fps=30 output_%d.png -y
It creates 300 consequent frames of my screen during 10 seconds period. Then I want to redirect the output to my nodejs app rather than just to write files on the hard drive. So I'm calling ffmpeg
from node:
var spawn = require('child_process').spawn,
fps = 30,
duration = 10,
screenSize = {w: 1366, h: 768},
args = [
'-t',
duration,
'-s',
screenSize.w + 'x' + screenSize.h,
'-f',
'x11grab',
'-i',
':0.0',
'-vf',
'fps=' + fps,
'-f',
'mjpeg',
'pipe:1'
],
ff = spawn('ffmpeg', args);
ff.stdout.on('data', function (data) {
console.log('Data size: ' + data.length);
});
ff.stdout.on('end', function (data) {
console.log('Stream end');
});
ff.stderr.on('data', function (data) {
console.log('ff error: ' + data);
});
I apologize for a long log, but it's important:
ff error: ffmpeg version N-77455-g4707497 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04)
configuration: --extra-libs=-ldl --prefix=/opt/ffmpeg --mandir=/usr/share/man --enable-avresample --disable-debug --enable-nonfree --enable-gpl --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb --disable-decoder=amrnb --disable-decoder=amrwb --enable-libpulse --enable-libdcadec --enable-libfreetype --enable-libx264 --enable-libx265 --enable-libfdk-aac --enable-libvorbis --enable-libmp3lame --enable-libopus --enable-libvpx --enable-libspeex --enable-libass --enable-avisynth --enable-libsoxr --enable-libxvid --enable-libvo-aacenc --enable-libvidstab
libavutil 55. 11.100 / 55. 11.100
libavcodec 57. 20.100 / 57. 20.100
libavformat 57. 20.100 / 57. 20.100
libavdevice 57. 0.100 / 57. 0.100
libavfilter 6. 21.101 / 6. 21.101
libavresample 3. 0. 0 / 3. 0. 0
libswscale 4. 0.100 / 4. 0.100
libswresample 2. 0.101 / 2. 0.101
libpostproc 54. 0.100 / 54. 0.100
ff error: Input #0, x11grab, from ':0.0':
Duration: N/A, start: 1451414448.216650, bitrate: N/A
Stream #0:0: Video: rawvideo (BGR[0] / 0x524742), bgr0, 1366x768, 29.97 fps, 29.97 tbr, 1000k tbn,
ff error: 29.97 tbc
ff error: [swscaler @ 0x34238a0] deprecated pixel format used, make sure you did set range correctly
ff error: Output #0, mjpeg, to 'pipe:1':
Metadata:
encoder :
ff error: Lavf57.20.100
Stream #0:0: Video: mjpeg, yuvj444p(pc), 1366x768, q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc
Metadata:
encoder : Lavc57.20.100 mjpeg
Side data:
unknown side data type 10 (24 bytes)
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> mjpeg (native))
Press [q] to stop, [?] for help
ff error: [swscaler @ 0x34238a0] Warning: data is not aligned! This can lead to a speedloss
Data size: 65536
Data size: 65536
Data size: 21413
Data size: 65536
Data size: 65536
Data size: 45581
Data size: 65536
Data size: 65536
Data size: 62377
Data size: 65536
Data size: 65536
Data size: 45581
Data size: 65536
Data size: 65536
Data size: 21413
Data size: 65536
Data size: 60933
Data size: 65536
Data size: 49550
Data size: 65536
Data size: 36709
Data size: 65536
Data size: 27035
Data size: 65536
Data size: 20131
Data size: 65536
Data size: 15887
Data size: 65536
Data size: 15887
Data size: 65536
Data size: 15887
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15911
ff error: frame= 16 fps=0.0 q=24.8 size= 1819kB time=00:00:00.53 bitrate=27935.6kbits/s speed=1.04x
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15919
Data size: 65536
Data size: 15919
Data size: 65536
Data size: 15919
Data size: 65536
Data size: 15919
Data size: 65536
Data size: 15919
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15906
Data size: 65536
Data size: 15906
Data size: 65536
Data size: 15917
Data size: 65536
Data size: 15999
Data size: 65536
Data size: 15949
Data size: 65536
Data size: 15997
Data size: 65536
Data size: 15965
ff error: frame= 32 fps= 30 q=24.8 size= 3092kB time=00:00:01.06 bitrate=23743.7kbits/s speed=1.01x
Data size: 65536
Data size: 16025
Data size: 65536
Data size: 15978
Data size: 65536
Data size: 15963
Data size: 65536
Data size: 16028
Data size: 65536
Data size: 15976
Data size: 65536
Data size: 15958
Data size: 65536
Data size: 15940
Data size: 65536
Data size: 15992
Data size: 65536
Data size: 15962
Data size: 65536
Data size: 16010
Data size: 65536
Data size: 15941
Data size: 65536
Data size: 15941
Data size: 65536
Data size: 15973
Data size: 65536
Data size: 15943
Data size: 65536
Data size: 15947
Data size: 65536
Data size: 15947
ff error: frame= 48 fps= 30 q=24.8 size= 4365kB time=00:00:01.60 bitrate=22349.6kbits/s speed=1.01x
Data size: 65536
Data size: 15982
Data size: 65536
Data size: 15982
Data size: 65536
Data size: 15956
Data size: 65536
Data size: 15956
Data size: 65536
Data size: 15956
Data size: 65536
Data size: 16001
Data size: 65536
Data size: 15930
Data size: 65536
Data size: 15922
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15911
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15985
Data size: 65536
Data size: 15985
ff error: frame= 64 fps= 30 q=24.8 size= 5638kB time=00:00:02.13 bitrate=21651.3kbits/s speed=1.01x
Data size: 65536
Data size: 15985
Data size: 65536
Data size: 15924
Data size: 65536
Data size: 15976
Data size: 65536
Data size: 15976
Data size: 65536
Data size: 15958
Data size: 65536
Data size: 16319
Data size: 65536
Data size: 16558
Data size: 65536
Data size: 16576
Data size: 65536
Data size: 16564
Data size: 65536
Data size: 16582
Data size: 65536
Data size: 16589
Data size: 65536
Data size: 16587
Data size: 65536
Data size: 16446
Data size: 65536
Data size: 16450
Data size: 65536
Data size: 16450
Data size: 65536
Data size: 16450
ff error: frame= 80 fps= 30 q=24.8 size= 6918kB time=00:00:02.66 bitrate=21251.0kbits/s speed=1.01x
Data size: 65536
Data size: 16568
Data size: 65536
Data size: 16575
Data size: 65536
Data size: 16585
Data size: 65536
Data size: 18182
Data size: 65536
Data size: 17203
Data size: 65536
Data size: 16769
Data size: 65536
Data size: 16734
Data size: 65536
Data size: 16823
Data size: 65536
Data size: 16338
Data size: 65536
Data size: 16455
Data size: 65536
Data size: 16406
Data size: 65536
Data size: 16645
Data size: 65536
Data size: 16800
Data size: 65536
Data size: 16800
Data size: 65536
Data size: 16800
Data size: 65536
Data size: 16806
ff error: frame= 96 fps= 30 q=24.8 size= 8204kB time=00:00:03.20 bitrate=21001.8kbits/s speed= 1x
Data size: 65536
Data size: 16795
Data size: 65536
Data size: 16804
Data size: 65536
Data size: 16770
Data size: 65536
Data size: 16760
Data size: 65536
Data size: 16813
Data size: 65536
Data size: 16445
Data size: 65536
Data size: 16259
Data size: 65536
Data size: 16260
Data size: 65536
Data size: 16265
Data size: 65536
Data size: 16284
Data size: 65536
Data size: 16233
Data size: 65536
Data size: 16233
Data size: 65536
Data size: 16182
Data size: 65536
Data size: 16058
Data size: 60561
ff error: frame= 111 fps= 30 q=24.8 size= 9384kB time=00:00:03.70 bitrate=20776.1kbits/s speed= 1x
Data size: 61813
Data size: 61813
Data size: 61813
Data size: 61813
Data size: 61813
Data size: 61781
Data size: 61784
Data size: 61796
Data size: 61842
Data size: 61839
Data size: 61793
Data size: 61810
Data size: 61844
Data size: 61844
Data size: 61850
Data size: 61841
ff error: frame= 127 fps= 30 q=24.8 size= 10350kB time=00:00:04.23 bitrate=20027.8kbits/s speed= 1x
Data size: 61858
Data size: 61853
Data size: 61833
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
ff error: frame= 142 fps= 30 q=24.8 size= 11256kB time=00:00:04.73 bitrate=19480.5kbits/s speed= 1x
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
ff error: frame= 158 fps= 30 q=24.8 size= 12223kB time=00:00:05.26 bitrate=19011.4kbits/s speed= 1x
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61867
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 173 fps= 30 q=24.8 size= 13129kB time=00:00:05.76 bitrate=18650.3kbits/s speed= 1x
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 188 fps= 30 q=24.8 size= 14035kB time=00:00:06.26 bitrate=18346.6kbits/s speed= 1x
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 203 fps= 30 q=24.8 size= 14941kB time=00:00:06.76 bitrate=18087.8kbits/s speed= 1x
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 219 fps= 30 q=24.8 size= 15907kB time=00:00:07.30 bitrate=17850.8kbits/s speed= 1x
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 234 fps= 30 q=24.8 size= 16813kB time=00:00:07.80 bitrate=17658.1kbits/s speed= 1x
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
Data size: 61850
ff error: frame= 250 fps= 30 q=24.8 size= 17780kB time=00:00:08.33 bitrate=17478.0kbits/s speed= 1x
Data size: 61850
Data size: 61712
Data size: 61712
Data size: 61712
Data size: 61712
Data size: 61712
Data size: 61712
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
ff error: frame= 265 fps= 30 q=24.8 size= 18675kB time=00:00:08.83 bitrate=17319.4kbits/s speed= 1x
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
ff error: frame= 280 fps= 30 q=24.8 size= 19563kB time=00:00:09.33 bitrate=17171.2kbits/s speed= 1x
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
ff error: frame= 295 fps= 30 q=24.8 size= 20452kB time=00:00:09.83 bitrate=17038.0kbits/s speed= 1x
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
Data size: 60638
ff error: frame= 300 fps= 30 q=24.8 Lsize= 20748kB time=00:00:10.00 bitrate=16996.6kbits/s speed=0.998x
video:20748kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
Stream end
The error messages are weird too, but not the biggest problem for now, so let's omit them.
Looking at all the data coming from ffmpeg
I assume that the images are coming as a single stream without any separation. I don't think that looking into binary data and seeking for certain flag bytes is a good idea to solve the problem and separate the images. The command line I mentioned in the top of the post does separate writes to hard drive that means it produces separate writable streams per each screenshot. And it doesn't do so for a spawned process from nodejs.
What am I missing?
The solution is to use png-streamer and tune up ffmpeg args a little. png-streamer
parses the incoming stream and recognizes the PNG images by PNG binary header. Here's the final code:
var ffmpegArgs = [
'-t',
options.duration,
'-s',
options.width + 'x' + options.height,
'-f',
'x11grab',
'-i',
':' + options.display + '+' + options.offsetX + ',' + options.offsetY,
'-vf',
'fps=' + options.fps,
'-f', //<<
'image2pipe', //<<
'-vcodec', //<<
'png', //<<
'pipe:1'
],
ffmpeg = spawn('ffmpeg', ffmpegArgs);
new pngStreamer(ffmpeg, callback);
Along with helpful notes from comments there was a trick that -vcodec png
needs to be used as well. Otherwise the buffer comes in LAVC
format.