A FiveM/GTA V server resource that integrates with the Medal.tv desktop client to capture gameplay clips and screenshots. It supports manual capture and optional automatic capture based on ingame events, configurable via an ingame menu.
- Auto-Clipping UI: Toggle auto-clipping, configure clip length, and enable/disable specific events.
- Custom Event Signals: Dynamically register your own clipping events at runtime via the
registerSignal
export. - SuperSoaker Screenshots: Drop-in replacement for
screenshot-basic
with both local capture and HTTP upload. - GameVein Data Pipeline: Allows the Medal client to get game context and server info when clipping.
- Framework-Aware: The server detects framework (ESX → QBX → QB → ND → OX → TMC → unknown) and provides safe export helpers to avoid errors, without loading any framework resource files directly.
- FiveM server (FX Server from after 2020-05)
- Medal.tv client installed, and running on the player’s PC (to use the full features)
- Node.js LTS with pnpm installed (just to build the UI, one time, or avoid this with a Github release).
-
Place this resource folder into your server's
resources/
directory. -
In your server's
server.cfg
(or whatever config file your server uses to load resources), add the line below (replace with your actual folder name for this resource):ensure medal--fivem-resource
-
Start (or restart) your server.
- Ensure the Medal.tv desktop client is running before joining the server.
- Open the Medal UI in-game:
- Chat command:
/medal
(fromConfig.Command
) - Default keybind:
Page Up
(fromConfig.Keybind
)
- Chat command:
- In the UI, you can:
- Toggle auto-clipping on/off
- Set clip length
- Enable/disable individual events
Settings persist via resource KVPs; toggles and clip length are remembered per player.
You can configure automatic capture triggers through the ingame menu. Common examples include:
- Player deaths/downs
- Kills or headshots
Your server can enable/disable specific events to fit its gameplay style.
The UI has its own Node.js project under ui
. Use pnpm to install and build the UI.
-
Node.js LTS
-
pnpm installed globally:
npm i -g pnpm
-
From the
ui
directory, install dependencies:pnpm install
-
Build the UI assets:
pnpm build
-
This builds
ui/src
intoui/dist
, which is the NUI loaded by the resource/FXServer.
config.lua
Config.Command
andConfig.Keybind
control how players open the UI.Config.ClippingEvents
pre-registers events visible in the Auto-Clipping UI.Config.Screenshots
MedalPreferred
: Prefer Medal.tv for screenshots when available.ScreenshotBasicOverride
: Provides compatibility forscreenshot-basic
exports.
-
fillSoaker(options?: SoakerOptions, cb: fun(data:string))
-
Capture a screenshot and return a Data URI to the callback.
-
Example:
--//=-- Local screenshot as Data URI exports['medal--fivem-resource']:fillSoaker({ encoding = 'jpg', quality = 0.92 }, function(data) TriggerEvent('chat:addMessage', { template = '<img src="{0}" style="max-width: 300px;" />', args = { data } }) end)
-
-
shootWater(url: string, field: string, options?: SoakerOptions, cb: fun(result:string))
-
Capture a screenshot and upload as
multipart/form-data
tourl
, invoking the callback with the HTTP response text. -
Example:
--//=-- Upload screenshot exports['medal--fivem-resource']:shootWater('https://your-upload/endpoint', 'file', { encoding = 'jpg', quality = 0.9, headers = { Authorization = 'Bearer XYZ' } }, function(resp) print('upload result', resp) end)
-
-
registerSignal(event: string, options: EventConfig)
-
Dynamically register a custom auto-clipping event with the UI and handler.
-
Example:
--//=-- Register a custom event; when `my:custom:event` is triggered, a clip request is sent exports['medal--fivem-resource']:registerSignal('my:custom:event', { id = 'my_custom_event', title = 'My Custom Event', desc = 'Triggers on my custom event', enabled = true, tags = { 'custom' } })
-
Event configs define how an auto-clipping event appears and behaves in the UI. See clipping/__types.lua
.
EventConfig = {
id: string, -- unique id used internally and for persistence
title: string, -- display name in the UI
desc?: string, -- optional description shown in the UI
enabled?: boolean, -- whether the event is enabled by default
tags?: string[], -- optional tags passed along with clip requests
}
requestPlayerWater(player: number, options: SoakerOptions, cb: fun(err:any|false, data:string, src:number))
-
Ask a specific player to capture a screenshot; the callback receives a Data URI.
-
Example:
--//=-- Request a screenshot from a player exports['medal--fivem-resource']:requestPlayerWater(source, { encoding = 'png' }, function(err, data, src) if err then print('screenshot error', err) return end print(('player %s returned %d bytes'):format(src, #data)) end)
-
- When
Config.Screenshots.ScreenshotBasicOverride = true
, the resource provides handlers compatible withscreenshot-basic
client/server exports (fill/upload and request client screenshot). Prefer thefillSoaker
/shootWater
/requestPlayerWater
exports shown above for consistent behavior.
-
Core
-
UI
-
Utilities
If you encounter issues, or want to suggest new auto-clipping events, please open an issue or PR.