- Notifications
You must be signed in to change notification settings - Fork15
Media playback library for Garry's Mod.
License
wyozi/gmod-medialib
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Media library for Garry's Mod.
Awesomium (the embedded web browser) in Garry's Mod doesn't work with Youtube. To fix this you need to use thechromium
branch for Garry's Mod. See#64 for details.
- Download
medialib.lua
or minimizedmedialib.min.lua
fromhttps://github.com/wyozi/gmod-medialib/releases/latest and place into your addon/gamemode - Make sure it is available to clients via
AddCSLuaFile
- Include it where-ever you need it. See best-practises below:
local medialib = include("the/path/to/medialib.lua")
if you only use it in one fileMyGlobalTable.medialib = include("the/path/to/medialib.lua")
if you use it multiple times (you need to refer to medialib asMyGlobalTable.medialib
or localize it if you do this)
- Setup API keys as needed (see Configuration section below)
Medialib offers some configuration options that can be set by setting members of the imported medialib object.
-- Example library importlocalmedialib=include("medialib.lua")-- SoundCloud API key. Required for SoundCloud service-- Can also be a table in which case a random key is picked for each query.medialib.SOUNDCLOUD_API_KEY="my-key-here"-- Youtube API key. Required for Youtube service-- If you want to generate your own you can do so at https://console.developers.google.com/apis/dashboardmedialib.YOUTUBE_API_KEY="my-key-here"-- The maximum number of HTML panel instances in the HTML pool-- Set this to a sensible number (1-5) if you spawn a lot of HTML mediasmedialib.MAX_HTMLPOOL_INSTANCES=0
-- If existing global reference exists, remove themifIsValid(CLIP)thenCLIP:stop()endlocallink="https://www.youtube.com/watch?v=6IqKEeRS90A"-- Get the service that this link uses (eg. youtube, twitch, vimeo, webaudio)localservice=medialib.load("media").guessService(link)-- Create a mediaclip from the linklocalmediaclip=service:load(link)-- Store global reference for debugging purposesCLIP=mediaclip-- Play mediamediaclip:play()-- Draw videohook.Add("HUDPaint","DrawVideo",function()localw=500localh=w* (9/16)mediaclip:draw(0,0,w,h)surface.SetDrawColor(255,255,255)surface.DrawRect(0,h,w,25)-- Request metadata. 'meta' will be nil if metadata is still being fetched.-- Note: this is a clientside shortcut to Service#query. You should use Service#query on serverside.localmeta=mediaclip:lookupMetadata()localtitle,duration=tostring(metaandmeta.title),(metaandmeta.duration)or0draw.SimpleText(title,"DermaDefaultBold",5,h+3,Color(0,0,0))localtimeStr=string.format("%.1f / %.1f",mediaclip:getTime(),duration)draw.SimpleText(timeStr,"DermaDefaultBold",w-5,h+3,Color(0,0,0),TEXT_ALIGN_RIGHT)end)
Seeexamples/
for more elaborate examples.
- Server ⇋ Client
Medialib provides no means of communication between server and client. This means that to for example synchronize video between clients, you must handle networking the media URL and the media start time yourself.
For this purpose you might find myNetTable library useful, but medialib itself contains no networking code.
- Client
On clientside medialib uses either HTML Awesomium panels or BASS sound objects for playback.
HTML panels are relatively expensive way to playback videos, but having one or two of them should work fine.BASS sound objects (which are used for webaudio and webradio) are pretty cheap. There should be no problem having many of them playing at the same time if needed.
In a nutshell you should use mp3 or ogg files when possible, as they are way cheaper for media playback, but for things like media players that must accept Youtube links HTML media works fine.If there can be arbitrary amount of player controlled jukeboxes on the map, you might want to add some limitations so eg. more than two cannot play simultaneously.
- Shared (server and client)
Both server and client have the ability to query for video metadata.
This is not instant, as HTTP queries used for majority of services take their time, but querying for metadata is pretty cheap as long as you don't do it in a Think hook or similar.
Method | Description | Notes |
---|---|---|
medialib.load("media").guessService(url, [opts]) | Returns aService object based on the URL. Returnsnil if there is no service for the URL. | Note |
Service:load(url, options) | Creates aMedia object using the URL | |
Service:query(url, callback) | Queries for metadata about video (eg.title andduration ) | |
Media:on(name, listener) | Adds an event listener. See below for a list of events | |
Media:isValid() | Returns a boolean indicating whether media is valid | Note |
Media:getServiceBase() | Returns the media service type, which is one of the following: "html", "bass" | |
Media:getService() | Returns the service from which this media was loaded | |
Media:getUrl() | Returns the original url passed toService:load , from which this media was loaded | |
Media:lookupMetadata() | Returns metadata if it's cached. Otherwise queries service for metadata and returns nil. | Note |
Media:play() | Plays media. Aplaying event is emitted when media starts playing. | |
Media:pause() | Pause media. Apaused event is emitted when media pauses. | |
Media:stop() | Pause media. Astopped event is emitted when media stops. | |
Media:getState() | Returns state of media, which is one of the following: "error", "loading", "buffering", "playing", "paused", "stopped" | Note |
Media:isPlaying() | Returns a boolean indicating whether media is playing. UsesgetState() . | |
Media:setVolume(vol) | Sets volume.vol must be a float in the range of 0 and 1. | |
Media:getVolume() | Returns the volume (a float in the range of 0 and 1). | |
Media:setQuality(qual) | Sets quality.qual must be one of the following: "low", "medium", "high", "veryhigh" | Note |
Media:getTime() | Returns the elapsed time | |
Media:seek(time) | Seeks to specified time. | Note |
Media:sync(time, errorMargin) | Seeks to given time, if the elapsed time differs from it too much (more than errorMargin) | Note |
Media:runCommand(fn) | Runs a command after media has loaded or immediately if it is already loaded |
Media
Event name | Parameters | Description |
---|---|---|
playing | Called when media starts playing | |
paused | Called when media is paused | |
buffering | Called when media is buffering. Aplaying event is emitted when buffering stops. | |
ended | { stopped = bool } | Called when media ends.stopped is true if ended by call toclip:stop() |
destroyed | Called when media is destroyed/invalidated.isValid() will return false after this | |
error | errorId errorDesc | Called when media fails to play.errorId is short error identifier.errorDesc is a longer string type description. |
Medialib calls some hooks. You can use Garry's Mod'shook.Add
to hook them and modify extend medialib's functionality.
Medialib_ProcessOpts(Media mediaObj,table opts)Called before media is loaded but after it is created with the options passed toService:load(url, options)
. You can use this hook to add new methods to the media object or set variables. Maybe even queue some things withMedia:runCommand(fn)
.
Medialib_ExtendQuery(string url,CallbackChainObj cbchain)Can be used to add additional data to queried data. Because data querying requires callbacks and medialib doesn't have promises, it uses really hardcore callback chainer, which can be found fromservicebase.lua
.
About
Media playback library for Garry's Mod.