This wiki page presents a script written to provide manual control of exposure settings during the video recording. It should work with all CHDK enabled Canon P&S cameras. Please check if your model has been tested (below) and if not, please report any testing results.
Forum Thread : Video Manual Control
Download Link : videxp3.lua
Operation
To use this script, place the camera into video recording mode. When the script is activated, a GUI input box will open on the bottom of the camera LCD screen. Use the camera keyboard keys to control the GUI. The right & left keys change fields. The up & down keys to change the exposure values in each field. Use the DISP/SET button to start and stop video recording. The MENU key or a shutter button full press will end script execution.
Note : using this script requires that Lua Native Calls be enabled in the CHDK Miscellaneous menu. See the warning below about the use of native calls.
Configuration
Configuration Options are :
- Starting Tv (sec) : set the default shutter speed to be used when the script starts
- Staring Av (f-stop) : set the default lens aperture opening to be used when the script starts
- Staring ISO : set the default ISO sensitiviy setting to be use used when the script starts
- ISO Max : set the maximum value the script will allow for ISO adjustment. One some cameras, too high a value will cause the script to shut down
- Show start message : enables a startup help screen
- Debug mode : enable the script console - useful if the script does not seem to be working.
Warning
Use this script at you own risk. This script makes native calls to the Canon firmware in order to manipulate exposure settings during video recording. While it is generally believed safe to do so, and this code has been tested on many camera models, it is potentially more risky that standard CHDK activities.
Results may also vary between different camera models so if you test this script and find it works for your camera please report it here.
Tested Cameras
(please add any additional cameras tested here - please note any failures too)
- A Series: A720 A1200
- G series: G10 , G12
- IXUS series: IXUS120_SD940
- S series: S110
- SX series : SX130is SX150is SX220hs SX260hs SX50hs
Failures :
- SX50hs hangs when ISO3200 selected, works fine otherwise if mode dial set to Video
- G12 failed with script versions prior to 3.3
- G1X fails
Lua Script
videxp3.lua : for CHDK v1.3.0 or greater
hint : you can download the most recent version of the script from the link posted at the top of this page
--[[
@title Video Exp Ctrl v3.1
original script by fudgey 2010/08/23
http://chdk.setepontos.com/index.php?topic=5295.msg68622#msg68622
modified 2013/11/29 by waterwingz & msl
@param t Starting Tv (sec)
@default t 3
@values t 1/30 1/60 1/100 1/200 1/400 1/640 1/800 1/1000 1/1250 1/1600 1/2000
@param a Starting Av (f-stop)
@default a 7
@values a 1.8 2.0 2.2 2.6 2.8 3.2 3.5 4.0 4.5 5.0 5.6 6.3 7.1 8.0
@param p Starting ISO
@default p 1
@values p 80 100 200 400 800 1250 1600
@param q ISO Max
@default q 4
@values q 100 200 400 800 1250 1600 3200
@param s Show Start Message ?
@default s 1
@range s 0 1
@param d Debug Mode ?
@default d 0
@range d 0 1
--]]
require("drawings")
props=require("propcase")
-- ========================== Functions =================================
function restore()
if ( get_movie_status() == 4 ) then
if ( vbutton == 1 ) then press("video") sleep(500) release("video")
else press("shoot_full") sleep(250) release("shoot_full") end
end
set_aelock(0)
set_console_autoredraw(0)
end
tv_ref = { -- note : tv_ref values set 1/2 way between shutter speed values
464, 496, 528, 560, 592, 624, 656,
688, 720, 752, 784, 816, 848, 880, 912, 944, 976,
1008, 1040, 1072, 1096, 1129, 1169, 1192, 1225, 1265, 1376 }
tv_val = {
400,
471, 511, 542, 567, 607, 638, 669,
703, 734, 765, 799, 830, 861, 895, 926, 957, 988,
1022, 1053, 1084, 1118, 1149, 1180, 1214, 1245, 1276 }
tv_str = {
"err",
"1/30", "1/40", "1/50", "1/60", "1/80", "1/100", "1/125",
"1/160", "1/200", "1/250","1/320","1/400","1/500","1/640","1/800","1/1000","1/1250",
"1/1600","1/2000","1/2500","1/3200","1/4000","1/5000","1/6400","1/8000","1/10000","hi" }
function print_tv(val)
if ( val == nil ) then return("-") end
local i = 1
while (i <= #tv_ref) and (val > tv_ref[i]) do i=i+1 end
return tv_str[i]
end
av_table = {163, 192, 218, 254, 285, 322, 347, 384, 417, 446, 477, 510, 543, 576, 609, 638, 664, 710, 731, 768}
function print_av(val)
if ( val == nil ) then return("-") end
local fstop=av96_to_aperture(val)
return((fstop/1000).."."..(fstop%1000)/100)
end
sv_table = { 380, 411, 507, 603, 699, 795, 891 }
function print_sv(val)
if ( val == nil ) then return("-") end
return( ((iso_real_to_market(sv96_to_iso(val))+5)/10)*10 )
end
function screen_w() -- lookup table for 480 px screen
local cams = "ixus110_sd960|ixus200_sd980|ixus240_elph320hs|ixus300_sd4000|ixus310_elph500hs|ixus1000_sd4500|sx1|sx210is|sx220hs|sx230hs"
return string.find(cams, get_buildinfo().platform) and 480 or 360
end
function help_screen()
local x = screen_w()/2 - 132
local help_msg = { "HELP SCREEN","FUNC/SET : start/stop video","\017 \016 : change field", "\030 \031 : change value", "MENU : exit", "FULLPRESS : exit", "Press any key to start", " "}
local i=1
while (i < #help_msg) do
msg = " "..(help_msg[i]).." "
inx = string.find(msg,":")
if (inx ~= nil) then
draw.add( "string", x, i*16+64, string.sub(msg, inx-12, inx+18), "red","white")
else
draw.add( "string", x, i*16+64, string.sub(msg, (#msg/2)-12, (#msg/2)+18),"white", "blue")
end
i=i+1
end
rec,vid,mode=get_mode()
if (vid ~= true) then
msg =" ".."**Camera not in video mode**".." "
draw.add( "string", x, i*16+64, string.sub(msg, (#msg/2)-12, (#msg/2)+18), "yellow","red")
end
repeat
draw.overdraw()
wait_click(100)
until not(is_key("no_key"))
draw.clear()
end
function draw_box()
local fg, bg = "blue" , "black"
local w = box_width
local h = box_height
--if (gb ~= "trans") then
draw.add("rectf", xpos-1, ypos-6, xpos+w+1, ypos+h+1, bg, bg)
--end
draw.add("string", xpos, ypos-6, " Tv Av Sv", fg, bg)
draw.add("line", xpos, ypos, xpos+20, ypos, fg)
draw.add("line", xpos+45, ypos, xpos+70, ypos, fg)
draw.add("line", xpos+100, ypos, xpos+120, ypos, fg)
draw.add("line", xpos+150, ypos, xpos+w, ypos, fg)
draw.add("line", xpos, ypos, xpos, ypos+h, fg)
draw.add("line", xpos+w, ypos, xpos+w, ypos+h, fg)
draw.add("line", xpos, ypos+h, xpos+w, ypos+h, fg)
end
function init_values()
local fg, bg = "blue" , "black"
val1=draw.add("string", xpos+6, ypos+12, " -", fg, bg)
val2=draw.add("string", xpos+76, ypos+12, " -" , fg, bg)
val3=draw.add("string", xpos+120, ypos+12, " -" , fg, bg)
end
function show_values(Tv, Av, Sv)
local fg, bg = "white" , "black"
local fg1, fg2, fg3, fg4, bg1, bg2, bg2 , bg3, bg4
if(gui_index==0) then fg1 = bg bg1=fg else fg1 = fg bg1=bg end
if(gui_index==1) then fg2 = bg bg2=fg else fg2 = fg bg2=bg end
if(gui_index==2) then fg3 = bg bg3=fg else fg3 = fg bg3=bg end
draw.replace(val1, "string", xpos+6, ypos+12, string.sub(" "..print_tv(Tv).." ",0,8), fg1, bg1)
draw.replace(val2, "string", xpos+76, ypos+12, string.sub(" "..print_av(Av).." ",0,5), fg2, bg2)
draw.replace(val3, "string", xpos+120, ypos+12, string.sub(" "..print_sv(Sv).." ",0,5), fg3, bg3)
end
function adjust_value(inx, offset)
local i=1
if (inx==0 ) then -- adjust Tv value
while (i <= #tv_ref) and ( tv96 > tv_ref[i]) do i=i+1 end
if ( offset > 0 ) then tv96=tv_val[math.min(#tv_val,i+1)]
else tv96=tv_val[math.max(2,i-1)] end
while (i <= #tv_ref) and ( tv96 > tv_val[i]) do i=i+1 end
tv96ret=call_event_proc("SetAE_ShutterSpeed",tv96)
if ((tv96ret < tv96-96) or (tv96ret > tv96+96))then -- clamp values beyond cameras range
print("clamp", tv96ret)
tv96=tv96ret
end
print("new Tv96=",tv96)
elseif (inx==1) then -- adjust Av value
av96old = av96
while (i <= #av_table) and ( av96 > av_table[i]) do i=i+1 end
if ( offset > 0) then
repeat -- find next f-stop value the camera will accept
av96=av_table[math.min(#av_table,i)]
av96ret=call_event_proc("MoveIrisToAv",av96)
i=i+1
until (i > #av_table) or (av96ret>av96old)
av96=av96ret
else
repeat
i=i-1
av96=av_table[math.max(1,i)]
av96ret=call_event_proc("MoveIrisToAv",av96)
until (i==1) or (av96ret<av96old)
av96=av96ret
end
print("new Av96=",av96)
elseif (inx==2) then -- adjust Sv value
while (i <= #sv_table) and ( sv96 > sv_table[i]) do i=i+1 end
if ( offset > 0) then sv96=sv_table[math.min(#sv_table,i+1)]
else sv96=sv_table[math.max(1,i-1)] end
call_event_proc("SetCDSGain",sv96)
print("new Sv96=",sv96)
end
end
-- ========================== Main Program =================================
tv_table = { 471, 567, 640, 736, 832, 896, 928, 960, 992, 1024, 1056, 1180, 1276}
tv96target = tv_table[t+1]
av_table = { 171, 192, 218, 265, 285, 322, 347, 384, 417, 446, 477, 510, 543, 576 }
av96target = av_table[a+1]
sv_table = { 381, 411, 507, 603, 699, 761, 795, 891 }
sv96target = sv_table[p+1]
sv96max = sv_table[p+2]
xpos = screen_w()/2 -110 -- msl: 360 or 480 px for default screen position & size (upper left hand corner)
ypos = 175 -- msl: above the warning text of the unlimited video recording time
box_width = 170
box_height = 32
set_console_layout(1 ,4, 45, 16 )
bi=get_buildinfo()
print(string.format("%s %s-%s %s %s %s", bi.version, bi.build_number, bi.build_revision, bi.platform, bi.platsub, bi.build_date))
version= tonumber(string.sub(string.gsub(get_buildinfo().build_number, "%p", ""), 0, 3))
if ( tonumber(bi.build_revision) > 0 ) then build = tonumber(bi.build_revision)
else build = tonumber(string.match(bi.build_number,'-(%d+)$')) end
if ( version < 130) or ( build < 3250) then
error("CHDK 1.3.0 or higher, build 3250 or higher, required")
end
if (type(call_event_proc) ~= "function" ) then -- need native calls turned on
error("Lua native calls not enabled")
end
if (call_event_proc("FA.Create") == -1) then -- required for event procedures SetAE_ShutterSpeed, MoveIrisToAv, SetCDSGain
error("FA CREATE failed")
end
if (call_event_proc("InitializeAdjustmentSystem") == -1) then
error("InitializeAdjustmentSystem failed")
end
-- switch to shooting mode & make sure we are in a video mode
if ( get_mode() == false ) then
sleep(1000)
set_record(1)
while ( get_mode() == false) do sleep(100) end
end
sleep(500)
-- setup splash screen & console
set_console_autoredraw(d -1)
cls()
if (s==1) then help_screen() end
set_exit_key("no_key") -- use "menu" key to exit so that recording gets stopped if running
set_draw_title_line(0)
vbutton = get_video_button()
-- startup values
set_aelock(1) -- go to manual exposure mode
tv96=call_event_proc("SetAE_ShutterSpeed",tv96target)
av96=call_event_proc("MoveIrisToAv",av96target)
call_event_proc("SetCDSGain",sv96target)
sv96=sv96target
draw_box()
init_values()
gui_index=0
while true do
show_values(tv96, av96, sv96)
repeat
draw.overdraw()
wait_click(200)
until not(is_key("no_key"))
if is_pressed("set") then
if ( vbutton == 1 ) then press("video") sleep(1000) release("video") sleep(1000)
else press("shoot_full") sleep(1000) release("shoot_full") sleep(1000) end
elseif is_pressed("left") then
if gui_index > 0 then gui_index = gui_index - 1 end
elseif is_pressed("right") then
if gui_index < 2 then gui_index = gui_index + 1 end
elseif ( is_key("up")) then
adjust_value(gui_index, 1)
elseif ( is_key("down")) then
adjust_value(gui_index, -1)
elseif ( is_key("zoom_in")) then
press("zoom_in")
while(is_pressed("zoom_in")) do sleep(20) end
release("zoom_in")
elseif ( is_key("zoom_out")) then
press("zoom_out")
while(is_pressed("zoom_out")) do sleep(20) end
release("zoom_out")
elseif (is_pressed("menu") or is_pressed("shoot_full")) then break
end
end
restore()