Skip to content

Instantly share code, notes, and snippets.

@d4rky-pl
Created July 29, 2016 09:25
Show Gist options
  • Save d4rky-pl/af949d878757242b3c70d6cf3e7902c5 to your computer and use it in GitHub Desktop.
Save d4rky-pl/af949d878757242b3c70d6cf3e7902c5 to your computer and use it in GitHub Desktop.
nio4r / non-blocking IO problem

I'm trying to implement running ffmpeg process with timeout without resorting to Ruby's Timeout class or spawning a new Thread with counter inside (that's how streamio-ffmpeg does it and it's error-prone and it feels wrong)

Unfortunately when doing non-blocking reads with nio4r, the size of returned chunks of data is pretty much random. While doing synchronous reads result in block yielding every line, in case of nio4r the polling makes it unpredictable.

Is there a better way or should I just somehow glue together responses when I somehow detect the response is incomplete?

Blocking
0: ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
1: built with Apple LLVM version 7.3.0 (clang-703.0.29)
2: configuration: --prefix=/usr/local/Cellar/ffmpeg/3.0.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-vda
3: libavutil 55. 17.103 / 55. 17.103
4: libavcodec 57. 24.102 / 57. 24.102
5: libavformat 57. 25.100 / 57. 25.100
6: libavdevice 57. 0.101 / 57. 0.101
7: libavfilter 6. 31.100 / 6. 31.100
8: libavresample 3. 0. 0 / 3. 0. 0
9: libswscale 4. 0.100 / 4. 0.100
10: libswresample 2. 0.101 / 2. 0.101
11: libpostproc 54. 0.100 / 54. 0.100
12: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f9219808600] moov atom not found
13: broken.mp4: Invalid data found when processing input
Non-blocking
0: ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
built with Apple LLVM version 7.3.0 (clang-703.0.29)
configuration: --prefix=/usr/local/Cellar/ffmpeg/3.0.2 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-vda
libavutil 55. 17.103 / 55. 17.103
libavcodec 57. 24.102 / 57. 24.102
libavformat 57. 25.100 / 57. 25.100
1: libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 31.100 / 6. 31.100
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
2: [mov,mp4,m4a,3gp,3g2,mj2 @ 0x7f9cd1000000] moov atom not found
broken.mp4: Invalid data found when processing input
require 'open3'
require 'nio'
file = 'broken.mp4'
output = 'output.mp4'
puts "Blocking"
stdin, _, stderr, thread = Open3.popen3("ffmpeg -i #{file} #{output}")
index = 0
stdin.close
while line = stderr.gets
puts "#{index}: #{line}"
index += 1
end
puts ""
puts "Non-blocking"
selector = NIO::Selector.new
stdin, _, stderr, thread = Open3.popen3("ffmpeg -i #{file} #{output}")
stderr_monitor = selector.register(stderr, :r)
index = 0
stderr_monitor.value = proc do
line = stderr_monitor.io.read_nonblock(4096)
puts "#{index}: #{line}"
index += 1
end
stdin.close
while thread.alive?
ready = selector.select(30)
begin
ready.each { |monitor| monitor.value.call }
rescue EOFError
break
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment