Last active
January 3, 2018 16:47
-
-
Save Jamie0/7fbe9c0b117ac954ca743c716490998c to your computer and use it in GitHub Desktop.
SEE https://github.com/InsanityRadio/automix ; Automatic Vision Mixer. Licensed under CC-BY-NC - contact me for commercial opportunities.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/env ruby | |
require 'rjoystick' | |
require 'atem' | |
require 'mysql2' | |
$AUDIO_THRESHOLD = 858803 * 2 | |
$IP = "10.0.0.1" | |
$JOYSTICK = "/dev/input/js0" | |
# CREATE TABLE link_history (`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, `start_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `end_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'); | |
$DATABASE = Mysql2::Client.new(:host => '10.0.0.0', :username => 'root', :password => 'toor', :databae => 'mic', :reconnect => true) | |
class Inputs | |
def initialize mapping, mixer | |
@mapping = mapping | |
@mixer = mixer | |
@k = Rjoystick::Device.new($JOYSTICK) | |
Thread.new do | |
loop do | |
begin | |
e = @k.event | |
handle_event e | |
rescue | |
STDERR.puts "Error in Joystick thread" | |
STDERR.p $! | |
@k.close rescue nil | |
@k = Rjoystick::Device.new($JOYSTICK) | |
end | |
end | |
end | |
end | |
def handle_event e | |
return unless e.type == Rjoystick::Event::JSBUTTON | |
return unless @mapping[e.number] != nil | |
e.value == 1 ? @mixer.enable(@mapping[e.number]) : @mixer.disable(@mapping[e.number]) | |
end | |
end | |
class VisionMixer | |
attr_accessor :close, :wide | |
def initialize ip, close, wide, slate | |
@ip = ip | |
@close = close | |
@wide = wide | |
@break = true | |
@current_camera = wide[0] | |
connect! | |
@close.map! { | w | @atem.inputs[w] } | |
@wide.map! { | w | @atem.inputs[w] } | |
@slate = @atem.inputs[slate] | |
end | |
def loop! | |
sleep 0 | |
loop do | |
select_camera | |
sleep 0 | |
# Make the camera live then start immediately gathering data again | |
live_camera | |
reset_peaks | |
sleep 2 | |
end | |
end | |
def connect! | |
@atem = ATEM.connect(@ip) | |
@atem.use_audio_levels = true | |
@atem.inputs[@current_camera].program | |
end | |
def enable camera | |
debug "Enabling #{camera}" | |
camera = @atem.inputs[camera] | |
@close << camera unless @close.include? camera | |
reload | |
end | |
def reload | |
old_break = @break | |
@break = @close.length == 0 | |
return unless old_break != @break | |
# Store it in the database - if there's now a break, end the current link. Otherwise, open one. | |
begin | |
if @break | |
$DATABASE.query "UPDATE link_history SET end_date = CURRENT_TIMESTAMP() WHERE end_date = 0;" | |
else | |
$DATABASE.query "INSERT INTO link_history (start_date, end_date) VALUES (CURRENT_TIMESTAMP(), 0);" | |
end | |
rescue | |
STDERR.puts "SQL Update failed!" | |
STDERR.send :p, $! | |
end | |
select_camera and live_camera | |
end | |
def disable camera | |
debug "Disabling #{camera}" | |
camera = @atem.inputs[camera] | |
@close.delete camera | |
reload | |
end | |
def select_camera | |
begin | |
@new_camera = (@wide + @close).sample | |
if @break | |
@new_camera = @slate | |
raise "Done" | |
end | |
if @wide.include? @current_camera | |
if Random.rand(3) == 0 | |
@new_camera = @wide.sample | |
raise "Done" | |
end | |
highest = [nil, $AUDIO_THRESHOLD] | |
p @close.length | |
@close.each do | cam | | |
maxim = [cam.audio.levels[:left_peak], cam.audio.levels[:right_peak]].max | |
highest = [cam, maxim] if maxim > highest[1] | |
end | |
if highest[0] != nil | |
p highest | |
@new_camera = highest[0] | |
raise "Done" | |
end | |
end | |
if @close.include? @current_camera | |
if Random.rand(3) == 0 | |
@new_camera = @wide.sample | |
raise "Done" | |
end | |
@new_camera = @close.sample | |
raise "Done" | |
end | |
@new_camera = @wide.sample | |
rescue | |
p $! | |
p $? | |
end | |
debug "Selected camera #{@new_camera.name}" | |
@new_camera.preview unless @current_camera == @new_camera | |
end | |
def live_camera | |
debug "#{@new_camera.name} is live" | |
@new_camera.program unless @current_camera == @new_camera | |
@current_camera = @new_camera | |
end | |
def reset_peaks | |
@atem.reset_audio_peaks | |
end | |
private | |
def info message | |
puts "[ INFO ] #{message}" | |
end | |
def debug message | |
puts "[ DEBUG ] #{message}" if $debug | |
end | |
end | |
$debug = true | |
# v = VisionMixer.new $IP, ['Pres', 'Gst'], ['Wide'], 'MP1' | |
v = VisionMixer.new $IP, [], ['Wide'], 'MP1' | |
Inputs.new ['Pres', 'Gst', 'Gst'], v | |
v.loop! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment