Some brands we've worked with…
Who we Work With
Our Creators
Meet the faces behind the ads.
Real Aussie creators, matched to your audience.
Process

Researching
We conduct in-depth research to understand your target audience's pain points and vernacular, ensuring our content resonates with them on a personal level.

Scripting
Our scripting process focuses on creating authentic narratives that reflect your brand's values.

Filming
We use engaging filming styles to enhance retention and set your brand apart from competitors.

Editing
Our meticulous editing ensures each piece of content flows seamlessly, making it effortless to watch.
Turnaround
Timeline
Comparison
Other Agencies
Horrible communication
Don't feel authentic
Outsourced mediocre talent

Constant, proactive communication
Testimonials
FAQs
// ReelSound — Code Override for the HeroReel (hero video carousel)
// Apply: select HeroReel > Code overrides > File: ReelSound > Override: withReelSound
//
// • No sound button. Every browser (phone, tablet, desktop) forces videos to
// start muted until the visitor interacts, so clips autoplay muted and the
// music switches on at the visitor's first tap / click / key press anywhere
// on the page.
// • If an interaction doesn't count (e.g. the end of a scroll on iPhone) it
// just tries again on the next one — it never gives up.
// • Smooth swaps: the moment you start swiping, the playing clip fades out.
// The next clip only gets sound once it has fully landed in the centre —
// it rewinds to the start while still silent, then fades in. No pops,
// no stutter, no sound flicking between clips mid-swipe.
// • Side clips stay muted. Reel auto-advance pauses while music plays.
// • Mutes while the reel is off-screen / the tab is hidden, and comes back
// automatically when the reel is visible again.
// • Remove the override at any time to revert — HeroReel.tsx is untouched
import {
forwardRef,
useEffect,
useRef,
useState,
useCallback,
type ComponentType,
} from "react"
import { RenderTarget } from "framer"
function isCanvas() {
try {
return RenderTarget.current() === RenderTarget.canvas
} catch {
return false
}
}
const GESTURES = [
"pointerdown",
"mousedown",
"pointerup",
"touchend",
"click",
"keydown",
]
const IGNORE_KEYS = [
"Shift",
"Control",
"Alt",
"Meta",
"Tab",
"CapsLock",
"Escape",
]
const FADE_IN_MS = 90
const FADE_OUT_MS = 70
const POLL_MS = 30
// iPhone / iPad ignore video.volume (always 1), so fades only run where supported
let volumeOK: boolean | null = null
function canSetVolume() {
if (volumeOK !== null) return volumeOK
try {
const t = document.createElement("video")
t.volume = 0.5
volumeOK = Math.abs(t.volume - 0.5) < 0.01
} catch {
volumeOK = false
}
return volumeOK
}
const fades = new WeakMap<HTMLVideoElement, number>()
function stopFade(v: HTMLVideoElement) {
const id = fades.get(v)
if (id) cancelAnimationFrame(id)
fades.delete(v)
}
function fadeTo(
v: HTMLVideoElement,
to: number,
ms: number,
done?: () => void
) {
stopFade(v)
if (!canSetVolume() || ms <= 0) {
try {
v.volume = to
} catch {}
done && done()
return
}
const from = v.volume
const start = performance.now()
const step = (now: number) => {
const k = Math.min(1, (now - start) / ms)
try {
v.volume = from + (to - from) * k
} catch {}
if (k < 1) fades.set(v, requestAnimationFrame(step))
else {
fades.delete(v)
done && done()
}
}
fades.set(v, requestAnimationFrame(step))
}
export function withReelSound(Component): ComponentType {
return forwardRef((props: any, ref) => {
const wrapRef = useRef<HTMLDivElement>(null)
const candRef = useRef<HTMLVideoElement | null>(null) // clip nearest the centre
const stableRef = useRef(0) // how many checks it has stayed there
const soundRef = useRef<HTMLVideoElement | null>(null) // clip allowed sound
const unlockedRef = useRef(false)
const primed = useRef(new WeakSet<HTMLVideoElement>())
const prepped = useRef(new WeakSet<HTMLVideoElement>()).current
const inViewRef = useRef(true)
const yieldRef = useRef(false)
const [soundOn, setSoundOn] = useState(false)
const [canvas] = useState(isCanvas)
const videos = useCallback(
() =>
wrapRef.current
? (Array.from(
wrapRef.current.querySelectorAll("video")
) as HTMLVideoElement[])
: [],
[]
)
// The clip nearest the middle of the reel, and whether it has landed
const findCentre = useCallback(() => {
const reel = wrapRef.current
?.firstElementChild as HTMLElement | null
const list = videos()
if (!reel || !list.length) return { v: null, settled: false }
const r = reel.getBoundingClientRect()
const cx = r.left + r.width / 2
let best: HTMLVideoElement | null = null
let bestD = Infinity
let bestW = 0
for (const v of list) {
const vr = v.getBoundingClientRect()
if (vr.width < 10) continue
const d = Math.abs(vr.left + vr.width / 2 - cx)
if (d < bestD) {
bestD = d
best = v
bestW = vr.width
}
}
return { v: best, settled: bestD < Math.max(10, bestW * 0.18) }
}, [videos])
const canPlayAudio = () =>
inViewRef.current && !document.hidden && !yieldRef.current
const silence = (v: HTMLVideoElement, quick = false) => {
if (v.muted) {
stopFade(v)
return
}
if (fades.has(v) && (v as any).__ceOut) return // already fading out
;(v as any).__ceOut = true
fadeTo(v, 0, quick ? 0 : FADE_OUT_MS, () => {
;(v as any).__ceOut = false
if (soundRef.current !== v) {
v.muted = true
try {
v.volume = 1
} catch {}
}
})
}
const fallBackMuted = (v: HTMLVideoElement) => {
stopFade(v)
v.muted = true
v.play().catch(() => {})
unlockedRef.current = false // retry at the next tap
soundRef.current = null
setSoundOn(false)
}
// Rewind while silent, then fade the music in
const bringIn = (v: HTMLVideoElement) => {
stopFade(v)
;(v as any).__ceOut = false
v.muted = true
let started = false
const go = () => {
if (started) return
started = true
v.removeEventListener("seeked", go)
if (soundRef.current !== v || !canPlayAudio()) return
if (canSetVolume()) {
try {
v.volume = 0
} catch {}
}
v.muted = false
const p = v.paused ? v.play() : null
if (p) p.catch(() => fallBackMuted(v))
fadeTo(v, 1, FADE_IN_MS)
}
const ready = prepped.has(v)
prepped.delete(v)
if (!ready && v.currentTime > 0.05) {
v.addEventListener("seeked", go)
try {
v.currentTime = 0
} catch {
go()
}
window.setTimeout(go, 150) // never wait forever
} else go()
if (v.paused) v.play().catch(() => {})
}
// Keep every clip's sound state correct
const sync = useCallback(() => {
const { v: cand, settled } = findCentre()
if (cand !== candRef.current || !settled) {
candRef.current = cand
stableRef.current = 0
} else stableRef.current++
const audible = unlockedRef.current && canPlayAudio()
const target =
audible && cand && settled
? cand
: null
const current = soundRef.current
// Rewind the incoming clip silently while it's still sliding in,
// so it's ready to go the instant it lands
if (audible && cand && cand !== current && !prepped.has(cand)) {
prepped.add(cand)
try {
cand.currentTime = 0
} catch {}
}
// Moving / off-screen: fade the playing clip out straight away
if (current && current !== target) {
const keep = !target && current === cand && settled && audible
if (!keep) {
soundRef.current = null
silence(current, !audible)
}
}
if (target && soundRef.current !== target) {
soundRef.current = target
bringIn(target)
} else if (target && target.paused) {
target.play().catch(() => fallBackMuted(target))
}
for (const v of videos()) {
if (v !== cand && v !== soundRef.current) prepped.delete(v)
if (v !== soundRef.current) {
if (!v.muted) silence(v, !audible)
}
if (v.paused) v.play().catch(() => {})
}
setSoundOn(!!soundRef.current)
}, [findCentre, videos])
useEffect(() => {
if (canvas) return
const reel = wrapRef.current?.firstElementChild
// Any real tap / click / key press switches music on
// (runs inside the gesture so iPhone / Safari allow it)
const onGesture = (e: Event) => {
if (
e.type === "keydown" &&
IGNORE_KEYS.includes((e as KeyboardEvent).key)
)
return
const t = e.target as Node | null
if (reel && t && reel.contains(t)) yieldRef.current = false
const ua = (navigator as any).userActivation
if (ua && !ua.isActive) return // e.g. end of a scroll — wait for a real tap
// Unlock each clip for sound ONCE (doing this on every tap
// caused little audio blips on iPhone while swiping)
for (const v of videos()) {
if (primed.current.has(v)) continue
if (v.muted) {
try {
v.volume = 0
} catch {}
v.muted = false
v.muted = true
try {
v.volume = 1
} catch {}
}
primed.current.add(v)
}
if (!unlockedRef.current) {
unlockedRef.current = true
// First unlock: start the centre clip inside the gesture
const { v: centre } = findCentre()
if (centre && canPlayAudio() && centre.muted) {
try {
centre.currentTime = 0
} catch {}
if (canSetVolume()) {
try {
centre.volume = 0
} catch {}
}
centre.muted = false
centre.play().catch(() => fallBackMuted(centre))
fadeTo(centre, 1, FADE_IN_MS)
soundRef.current = centre
candRef.current = centre
stableRef.current = 2
setSoundOn(true)
}
}
;[0, 120, 400].forEach((ms) => window.setTimeout(sync, ms))
}
// Another video on the page started playing with sound → step aside
const onPlay = (e: Event) => {
const t = e.target as HTMLVideoElement
if (
t &&
t.tagName === "VIDEO" &&
!t.muted &&
wrapRef.current &&
!wrapRef.current.contains(t)
) {
yieldRef.current = true
sync()
}
}
const onVis = () => sync()
let io: IntersectionObserver | null = null
if (reel && "IntersectionObserver" in window) {
io = new IntersectionObserver(
([entry]) => {
inViewRef.current = entry.isIntersecting
sync()
},
{ threshold: 0.35 }
)
io.observe(reel)
}
GESTURES.forEach((ev) =>
document.addEventListener(ev, onGesture, true)
)
document.addEventListener("play", onPlay, true)
document.addEventListener("visibilitychange", onVis)
const id = window.setInterval(sync, POLL_MS)
sync()
return () => {
io?.disconnect()
GESTURES.forEach((ev) =>
document.removeEventListener(ev, onGesture, true)
)
document.removeEventListener("play", onPlay, true)
document.removeEventListener("visibilitychange", onVis)
window.clearInterval(id)
}
}, [canvas, sync, findCentre, videos])
return (
<div ref={wrapRef} style={{ display: "contents" }}>
<Component
{...props}
ref={ref}
autoplay={soundOn ? false : props.autoplay}
/>
</div>
)
})
}

















