SERVICE.Name = "Direct Media" SERVICE.Id = "dm5" SERVICE.Base = "res" SERVICE.PrefetchMetadata = true SERVICE.FileExtensions = { "webm", "mp4", "mov", "mkv", "avi", "flv", "wmv", "m4v", "3gp", "ogv", "ts", "m2ts", "m3u8", "mpd", "png", "jpg", "jpeg", "gif", "webp", "avif", "apng", "bmp", "tiff", "tif", "ico", "svg" } DEFINE_BASECLASS( "mp_service_browser" ) local VideoMimeTypes = { webm = "video/webm", mp4 = "video/mp4", mov = "video/quicktime", mkv = "video/x-matroska", avi = "video/x-msvideo", flv = "video/x-flv", wmv = "video/x-ms-wmv", m4v = "video/mp4", ["3gp"] = "video/3gpp", ogv = "video/ogg", ts = "video/mp2t", m2ts = "video/mp2t", m3u8 = "application/x-mpegURL", mpd = "application/dash+xml" } local function IsStreamingFormat( ext ) ext = string.lower( ext or "" ) return ext == "m3u8" or ext == "mpd" end function SERVICE:IsTimed() if self._istimed == nil then self._istimed = self:Duration() > 0 end return self._istimed end if CLIENT then local JS_Pause = "if(window.MediaPlayer) MediaPlayer.pause();" local JS_Play = "if(window.MediaPlayer) MediaPlayer.play();" local JS_Volume = "if(window.MediaPlayer) MediaPlayer.volume = %s;" local JS_Seek = [[ if (window.MediaPlayer) { var seekTime = %s; var curTime = window.MediaPlayer.currentTime; var diffTime = Math.abs(curTime - seekTime); if (diffTime > 5) { window.MediaPlayer.currentTime = seekTime; } } ]] local VideoEmbedHTML = [[ ]] local ImageEmbedHTML = [[
]] function SERVICE:GetHTML() local url = self.url local path = self.urlinfo.path local ext = path and path:match("[^/]+%.(%S+)$") or "" if VideoMimeTypes[ext] then return VideoEmbedHTML:format(url) else return ImageEmbedHTML:format(url) end end function SERVICE:OnBrowserReady( browser ) if self._Paused then self.Browser:RunJavascript( JS_Play ) self._Paused = nil return end BaseClass.OnBrowserReady( self, browser ) local html = self.WrapHTML( self:GetHTML() ) browser:SetHTML( html ) end function SERVICE:Pause() BaseClass.Pause( self ) if IsValid(self.Browser) then self.Browser:RunJavascript(JS_Pause) end end function SERVICE:SetVolume( volume ) if not IsValid(self.Browser) then return end local js = JS_Volume:format( volume ) self.Browser:RunJavascript(js) end function SERVICE:Sync() local seekTime = self:CurrentTime() if IsValid(self.Browser) and self:IsTimed() and seekTime > 0 then self.Browser:RunJavascript(JS_Seek:format(seekTime)) end end function SERVICE:IsMouseInputEnabled() return IsValid( self.Browser ) end function SERVICE:PreRequest( callback ) local path = self.urlinfo.path local ext = path and path:match("[^/]+%.(%S+)$") or "" if IsStreamingFormat(ext) then self._metaDuration = 0 self._isStreaming = true callback() elseif VideoMimeTypes[ext] then MediaPlayerUtils.GatherVideoDuration( self.url, function(success, response) if success then self._metaDuration = response self._isStreaming = false callback() return end callback(response) end ) else self._metaDuration = 0 callback() end end function SERVICE:NetWriteRequest() net.WriteUInt( self._metaDuration or 0, 16 ) net.WriteBool( self._isStreaming or false ) end end if SERVER then function SERVICE:GetMetadata( callback ) local cached, found = self:GetCachedMetadata() if found then callback(cached) return end local metadata = {} local path = self.urlinfo.path local ext = path and path:match("[^/]+%.(%S+)$") or "" if not VideoMimeTypes[ext] then local filename = path and string.match(path, "([^/]+)%.%w-$") metadata.title = filename or self.url else metadata.title = self.url end metadata.duration = self._metaDuration or 0 self:SetMetadata(metadata, true) MediaPlayer.Metadata:Save(self) callback(self._metadata) end function SERVICE:NetReadRequest() if not self.PrefetchMetadata then return end self._metaDuration = net.ReadUInt( 16 ) self._isStreaming = net.ReadBool() end end