Getting Started
Welcome to the official documentation for the TV Labs' TV Automation Language (TVAL). If you're venturing into the realm of automation or are a seasoned developer looking for an adept scripting tool, you've come to the right place.
Background
TVAL is built upon the strengths of the renowned Lua programming language. It merges Lua's inherent simplicity with specialized modules tailored for streaming service development and QA tasks such as video analysis, automation, device control, and spatial navigation. For those familiar with Lua, you'll find the transition seamless. For newcomers, here's a taste of its elegance:
Please note that this example is for explanation purposes only. There are easier and more effective/efficent macros for capturing app start up time. Please see the examples folder.
local time, textWasFound = Timer.record(function ()
device.launchApp("Netflix")
-- Exclude this region from the test
local ignoreRegion = region.absolute(10, 10, 10, 10):invert()
local textFound = wait.forText("Home", { mask=ignoreRegion })
return textFound
end)
if textWasFound then
metric.record("appStartUp", time)
end
Key Features
Vision First
Unlike other platforms, TVAL is built upon vision instead of DOM traversal. This means that you'll approach problems in a more natural way leveraging your eyes and ears.
describe("Starting an episode", function ()
beforeEach(function ()
navigateTo(Pages.Episode(ANY))
end)
it("should start playing content", function ()
highlight(Pages.Episode.Start)
remote.press(Key.OK)
status = wait.forContent(Content.Start)
assert(status)
end)
it("should start playing content within 5 seconds", function ()
highlight(Pages.Episode.Start)
wait(seconds(10))
assert(content.isPlaying())
end)
end)
Because TVAL truly test end-user experience, the platform/tv os is no longer relevant. A single TVAL can be used across every device/platform as long as the interfaces are similar. Additionally, vision tests don't require refactoring when you change the structure of your code!
However, should you require access to HTML, TVAL implements the standard appium drivers under the hood.
Module-based Architecture
Our language is segmented into intuitive namespaces like remote
, screen
, and wait
, making functionalities easy to locate and implement. For example:
remote.press(Key.VolumeUp, Press.Long)
wait.forAudio(Volume.Increase)
local frame = screen.capture()
storage.put(frame, { name="Example Frame", key="example_frame_1" })
Abstracted Complexities
Through our vision interface we've abstracted away the majority of discrepencies between TV models. This allows you to write a script once and leverage it everywhere.
describe("Testing video progress bar ascross all tvs", function ()
setup(function ()
launchApp("Netflix")
end)
it("should show progress", function ()
app.playContent()
wait.forContent(Content.Playing)
progressBarRegion = region({ left=10, bottom=10, right=10, height=30 })
-- invert the region of the progress bar to mask everything else
mask = progressBarRegion:invert()
progressBarGrew = false
for currentFrame, lastFrame in motion({ mask=mask, duration=seconds(5) }) do
-- when it's the first frame there is no last frame
if not lastFrame then
return
end
-- Get the color from the masked region to see if the progress bar has grown
currentColorRegions = detect.color(App.Theme.PrimaryColor, currentFrame)
previousColorRegions = detect.color(App.Theme.PrimaryColor, lastFrame)
-- Check to see if the region has grown
if compare.isLarger(currentColorRegions, previousColorRegions) then
progressBarGrew = true
end()
end
end
assert(progressBarGrew)
end)
end)
Interact with Frames and Video
Screen Feedback
No more arbitrary delays! Introduce controlled pauses:
--- Instead of
remote.press(Key.OK)
wait(5000)
-- Do
remote.press(Key.OK)
wait.forContent(Content.Playing)
Remote Simulation
Simulate an array of remote control actions without physical interfaces:
remote.press(Key.OK)
remote.press(Key.OK, Press.Long)
remote.holdUntil(Key.OK, function (frame)
mask = region({ top=5, left=5, width=500, height=10 }):invert()
didFindText = detect.text("Home", frame, { mask: mask })
return didFindText
end)
remote.enterText("Hello World') -- automatically enter text into an onscreen keyboard
Please see the Remote API for full details
Community & Contributions
Echoing the spirit of open-source, we're open to contributions. Whether it's innovative feature suggestions, module expansions, or bug spotting, do refer to our contribution guidelines and get involved.
Conclusion
By harnessing the simplicity of Lua and enhancing it with our specialized modules, this scripting language stands as a robust tool for various applications. From intricate automation sequences to on-the-fly device management, the Custom Lua Scripting Language is geared to facilitate and elevate your projects.
Happy scripting, and we look forward to witnessing your innovations!