1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-27 04:11:33 +02:00
parent 901a510704
commit 48b64f3e4a
23 changed files with 345 additions and 72 deletions

View file

@ -1,5 +0,0 @@
fx_version 'cerulean'
games { 'gta5' }
author 'DTPL 3D <3d@dtpl.cz>'
description 'Touchdown Car Rental'
version '1.0.1'

View file

@ -1,21 +0,0 @@
<CodeWalkerProject>
<Name>New CodeWalker Project</Name>
<Version value="1" />
<YmapFilenames>
<Item>dtpl_carrent.ymap</Item>
<Item>hei_ap1_03_strm_2.ymap</Item>
</YmapFilenames>
<YtypFilenames>
<Item>dtpl_carrent.ytyp</Item>
</YtypFilenames>
<YbnFilenames />
<YndFilenames />
<YnvFilenames />
<TrainsFilenames />
<ScenarioFilenames />
<AudioRelFilenames />
<YdrFilenames />
<YddFilenames />
<YftFilenames />
<YtdFilenames />
</CodeWalkerProject>

View file

@ -9,6 +9,8 @@ local PlyInCarCam = false
local bcamstate = false local bcamstate = false
local carCam = false local carCam = false
local onRec = false local onRec = false
local isRecording = false
local isDashcamRecording = false
-- for prop and ped -- for prop and ped
local propNetID = nil local propNetID = nil
@ -767,22 +769,88 @@ RegisterNetEvent('spy-bodycam:client:deleteDecoyPed',function(plyId)
end) end)
RegisterNetEvent('spy-bodycam:client:startRec',function(webhook,serviceUsed) RegisterNetEvent('spy-bodycam:client:startRec',function(webhook,serviceUsed)
SendNUIMessage({ if isRecording then
action = "toggle_record", SendNUIMessage({action = "cancel_rec_force"})
hook = webhook, isRecording = false
service = serviceUsed, NotifyPlayer('Recording stopped!', 'success', 2500)
recTiming = Config.RecordTime,
}) if Config.ForceViewCam then
if Config.ForceViewCam then onRec = false
SetTimecycleModifier(Config.CameraEffect.bodycam) SetFollowPedCamViewMode(1)
SetTimecycleModifierStrength(0.5) SetTimecycleModifier('default')
CreateThread(function() SetTimecycleModifierStrength(1.0)
onRec = true end
while onRec do else
SetFollowPedCamViewMode(4) SendNUIMessage({
Wait(0) action = "toggle_record",
end hook = webhook,
end) service = serviceUsed,
recTiming = Config.RecordTime,
})
isRecording = true
NotifyPlayer('Recording started!', 'success', 2500)
if Config.ForceViewCam then
SetTimecycleModifier(Config.CameraEffect.bodycam)
SetTimecycleModifierStrength(0.5)
CreateThread(function()
onRec = true
while onRec do
SetFollowPedCamViewMode(4)
Wait(0)
end
end)
end
end
end)
RegisterNetEvent('spy-bodycam:client:startDashcamRec', function(webhook, serviceUsed, netId)
if isDashcamRecording then
SendNUIMessage({action = "stop_dashcam_recording"})
isDashcamRecording = false
NotifyPlayer('Dashcam recording stopped!', 'success', 2500)
if Config.ForceViewCam then
onRec = false
SetFollowPedCamViewMode(1)
SetTimecycleModifier('default')
SetTimecycleModifierStrength(1.0)
end
else
local veh = NetworkGetEntityFromNetworkId(netId)
if not DoesEntityExist(veh) then
NotifyPlayer('Vehicle not found!', 'error', 2500)
return
end
-- Get vehicle info for recording overlay
local carPlate = GetVehicleNumberPlateText(veh)
local carName = GetVehDisplayName(GetEntityModel(veh))
-- Send message to NUI to start recording
SendNUIMessage({
action = "toggle_dashcam_record",
hook = webhook,
service = serviceUsed,
recTiming = Config.RecordTime,
vehicleId = netId,
vehiclePlate = carPlate,
vehicleName = carName
})
isDashcamRecording = true
NotifyPlayer('Dashcam recording started!', 'success', 2500)
if Config.ForceViewCam then
SetTimecycleModifier(Config.CameraEffect.dashcam)
SetTimecycleModifierStrength(0.5)
CreateThread(function()
onRec = true
while onRec do
SetFollowPedCamViewMode(4)
Wait(0)
end
end)
end
end end
end) end)
@ -805,6 +873,39 @@ RegisterNetEvent('spy-bodycam:client:refreshRecords',function(records,isBoss)
}) })
end) end)
-- Register hotkeys for recording if enabled in config
if Config.EnableRecordingHotkeys then
-- Bodycam recording hotkey
RegisterKeyMapping('bodycamrecord', 'Start/Stop bodycam recording', 'keyboard', Config.RecordHotkey)
RegisterCommand('bodycamrecord', function()
if bcamstate then -- Only if bodycam is active
TriggerServerEvent('spy-bodycam:server:toggleRecording')
else
NotifyPlayer('Bodycam not activated!', 'error', 2500)
end
end)
-- Dashcam recording hotkey
RegisterKeyMapping('dashcamrecord', 'Start/Stop dashcam recording', 'keyboard', Config.DashcamHotkey)
RegisterCommand('dashcamrecord', function()
if IsPedInAnyVehicle(cache.ped, false) then
local veh = GetVehiclePedIsIn(cache.ped, false)
if isCarAuth(veh) then
local netId = NetworkGetNetworkIdFromEntity(veh)
if GlobalState.CarsOnBodycam[netId] then
TriggerServerEvent('spy-bodycam:server:toggleDashcamRecording', netId)
else
NotifyPlayer('Dashcam not activated in this vehicle!', 'error', 2500)
end
else
NotifyPlayer('Vehicle not authorized for dashcam!', 'error', 2500)
end
else
NotifyPlayer('You need to be in a vehicle to use dashcam!', 'error', 2500)
end
end)
end
RegisterKeyMapping('bodycamexit', 'Exit bodycam spectate', 'keyboard', Config.ExitCamKey) RegisterKeyMapping('bodycamexit', 'Exit bodycam spectate', 'keyboard', Config.ExitCamKey)
RegisterCommand('bodycamexit', function() RegisterCommand('bodycamexit', function()
if PlyInCam or PlyInCarCam then if PlyInCam or PlyInCarCam then
@ -827,7 +928,7 @@ RegisterNUICallback('videoLog', function(data, cb)
local videoUrl = data.vidurl local videoUrl = data.vidurl
local pos = GetEntityCoords(cache.ped) local pos = GetEntityCoords(cache.ped)
local s1, s2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z) local s1, s2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z)
TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl,GetStreetNameFromHashKey(s1)) TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl, GetStreetNameFromHashKey(s1), data.isDashcam)
end end
end) end)
@ -1041,6 +1142,7 @@ function PlayWatchAnim(ped,isNet)
Citizen.Wait(10) Citizen.Wait(10)
end end
local prop = CreateObject(tabletprop, x, y, z + 0.2, isNet, true, false) local prop = CreateObject(tabletprop, x, y, z + 0.2, isNet, true, false)
AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0,
AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true) AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true)
local animDict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a' local animDict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a'
RequestAnimDict(animDict) RequestAnimDict(animDict)
@ -1221,3 +1323,5 @@ function HasItemsCheck(itemname)
end end

View file

@ -21,10 +21,13 @@ Config.Dependency = {
UseProgress = 'qb', -- qb | ox | esx UseProgress = 'qb', -- qb | ox | esx
UseMenu = 'qb', -- qb | ox | esx UseMenu = 'qb', -- qb | ox | esx
UseNotify = 'qb', -- qb | ox | esx UseNotify = 'qb', -- qb | ox | esx
UseAppearance = 'illenium', -- qb | illenium | false UseAppearance = 'illenium', -- qb | illenium | false
} }
Config.ExitCamKey = 'BACK' Config.ExitCamKey = 'BACK'
Config.RecordHotkey = 'F9' -- Hotkey for bodycam recording
Config.DashcamHotkey = 'F10' -- Hotkey for dashcam recording
Config.EnableRecordingHotkeys = true -- Enable/disable hotkey functionality
Config.CameraEffect = { Config.CameraEffect = {
bodycam = 'Island_CCTV_ChannelFuzz', bodycam = 'Island_CCTV_ChannelFuzz',
@ -119,4 +122,4 @@ Config.VehCamOffset = {
-- 19: Military -- 19: Military
-- 20: Commercial -- 20: Commercial
-- 21: Trains -- 21: Trains
-- 22: Open Wheel -- 22: Open Wheel

View file

@ -161,13 +161,70 @@ Citizen.CreateThread(function()
end end
end) end)
RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetName) -- Handle bodycam recording toggle
RegisterNetEvent('spy-bodycam:server:toggleRecording', function()
local src = source
if PlayerOnBodycam[src] then
local defwebhook
if Upload.ServiceUsed == 'discord' then
local jobKey
if Config.Framework == 'qb' then
local Player = QBCore.Functions.GetPlayer(src)
jobKey = Player.PlayerData.job.name
else
local xPlayer = ESX.GetPlayerFromId(src)
jobKey = xPlayer.getJob().name
end
if Upload.JobUploads[jobKey] then
defwebhook = Upload.JobUploads[jobKey].webhook
else
defwebhook = Upload.DefaultUploads.webhook
end
elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
defwebhook = Upload.Token
end
TriggerClientEvent('spy-bodycam:client:startRec', src, defwebhook, Upload.ServiceUsed)
else
NotifyPlayerSv('Bodycam not turned on!', 'error', 3000, src)
end
end)
-- Handle dashcam recording toggle
RegisterNetEvent('spy-bodycam:server:toggleDashcamRecording', function(netId)
local src = source
if CarsOnBodycam[netId] then
local defwebhook
if Upload.ServiceUsed == 'discord' then
local jobKey
if Config.Framework == 'qb' then
local Player = QBCore.Functions.GetPlayer(src)
jobKey = Player.PlayerData.job.name
else
local xPlayer = ESX.GetPlayerFromId(src)
jobKey = xPlayer.getJob().name
end
if Upload.JobUploads[jobKey] then
defwebhook = Upload.JobUploads[jobKey].webhook
else
defwebhook = Upload.DefaultUploads.webhook
end
elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
defwebhook = Upload.Token
end
TriggerClientEvent('spy-bodycam:client:startDashcamRec', src, defwebhook, Upload.ServiceUsed, netId)
else
NotifyPlayerSv('Dashcam not turned on!', 'error', 3000, src)
end
end)
RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl, streetName, isDashcam)
local src = source local src = source
local offName local offName
local offJob local offJob
local offRank local offRank
local jobKey local jobKey
local date = os.date('%Y-%m-%d') local date = os.date('%Y-%m-%d')
local recordType = isDashcam and "dashcam" or "bodycam"
if Config.Framework == 'qb' then if Config.Framework == 'qb' then
local Player = QBCore.Functions.GetPlayer(src) local Player = QBCore.Functions.GetPlayer(src)
@ -184,12 +241,13 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
end end
---SQL UPLOAD ---SQL UPLOAD
MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername) VALUES (@job, @videolink, @street, @date, @playername)', { MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername, recordtype) VALUES (@job, @videolink, @street, @date, @playername, @recordtype)', {
['@job'] = jobKey, ['@job'] = jobKey,
['@videolink'] = videoUrl, ['@videolink'] = videoUrl,
['@street'] = streetName, ['@street'] = streetName,
['@date'] = date, ['@date'] = date,
['@playername'] = offName ['@playername'] = offName,
['@recordtype'] = recordType
}, function(rowsChanged) end) }, function(rowsChanged) end)
if Upload.DiscordLogs.Enabled then if Upload.DiscordLogs.Enabled then
@ -204,7 +262,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
end end
local embedData = { local embedData = {
{ {
title = Upload.DiscordLogs.Title, title = Upload.DiscordLogs.Title .. (isDashcam and " (Dashcam)" or " (Bodycam)"),
color = 16761035, color = 16761035,
fields = { fields = {
{ name = "Name:", value = offName, inline = false }, { name = "Name:", value = offName, inline = false },
@ -212,7 +270,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
{ name = "Job Rank:", value = offRank, inline = false }, { name = "Job Rank:", value = offRank, inline = false },
}, },
footer = { footer = {
text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()), text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()),
icon_url = "https://i.imgur.com/CuSyeZT.png", icon_url = "https://i.imgur.com/CuSyeZT.png",
}, },
author = author author = author
@ -370,4 +428,3 @@ AddEventHandler('onResourceStart', function(resourceName)
checkForUpdates() checkForUpdates()
end end
end) end)

View file

@ -79,9 +79,18 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Dashcam Recording UI -->
<div id="dashcam-recording-ui">
<div class="dashcam-header">
<div class="dashcam-recording-indicator"></div>
<span>DASHCAM RECORDING</span>
</div>
<div id="dashcam-vehicle-info">Police Cruiser - ABC123</div>
<div id="dashcam-timer">00:00</div>
</div>
<audio id="beep-sound" src="audio/on_sound.mp3"></audio> <audio id="beep-sound" src="audio/on_sound.mp3"></audio>
<audio id="off-sound" src="audio/off_sound.mp3"></audio> <audio id="off-sound" src="audio/off_sound.mp3"></audio>
<script src="js/jquery-3.7.1.min.js"></script> <script src="js/jquery-3.7.1.min.js"></script>
<script type="module" src="js/app.js"></script> <script type="module" src="js/app.js"></script>
</body> </body>
</html> </html>

View file

@ -1,7 +1,10 @@
import { GameView } from './gameview.js'; import { GameView } from './gameview.js';
const gameview = new GameView(); const gameview = new GameView();
let isRecording = false; let isRecording = false;
let isDashcamRecording = false;
let recordingTimeout; let recordingTimeout;
let dashcamRecordingTimeout;
let dashcamTimer;
$(document).ready(function () { $(document).ready(function () {
$('.overlayCont').hide(); $('.overlayCont').hide();
@ -10,6 +13,7 @@ $(document).ready(function () {
$('.recCont').hide(); $('.recCont').hide();
$('.askMain').hide(); $('.askMain').hide();
$('.vidplaycont').hide(); $('.vidplaycont').hide();
$('#dashcam-recording-ui').hide();
const beepSound = document.getElementById('beep-sound'); const beepSound = document.getElementById('beep-sound');
const offSound = document.getElementById('off-sound'); const offSound = document.getElementById('off-sound');
@ -98,7 +102,7 @@ $(document).ready(function () {
startRecording(data.hook, data.service); startRecording(data.hook, data.service);
recordingTimeout = setTimeout(() => { recordingTimeout = setTimeout(() => {
if (isRecording) { if (isRecording) {
// Stop recording automatically after 30 seconds // Stop recording automatically after configured time
isRecording = false; isRecording = false;
$('.HeadText').html('<i class="fa-solid fa-circle bodyIcon" style="color: white;"></i>' + 'Recording Stopped'); $('.HeadText').html('<i class="fa-solid fa-circle bodyIcon" style="color: white;"></i>' + 'Recording Stopped');
setTimeout(() => { setTimeout(() => {
@ -118,6 +122,53 @@ $(document).ready(function () {
stopRecording(); stopRecording();
} }
} }
if (data.action === 'toggle_dashcam_record') {
clearTimeout(dashcamRecordingTimeout);
if (!isDashcamRecording) {
// Start dashcam recording
isDashcamRecording = true;
$('#dashcam-recording-ui').show();
$('#dashcam-vehicle-info').text(`${data.vehicleName} - ${data.vehiclePlate}`);
// Start a timer for the dashcam recording
let seconds = 0;
dashcamTimer = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
$('#dashcam-timer').text(`${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`);
}, 1000);
// Start recording using the existing function
startRecording(data.hook, data.service, data.recTiming, true);
// Auto-stop after the configured time
dashcamRecordingTimeout = setTimeout(() => {
if (isDashcamRecording) {
isDashcamRecording = false;
$('#dashcam-recording-ui').hide();
clearInterval(dashcamTimer);
stopRecording(true);
}
}, data.recTiming * 1000);
} else {
// Stop dashcam recording
isDashcamRecording = false;
$('#dashcam-recording-ui').hide();
clearTimeout(dashcamRecordingTimeout);
clearInterval(dashcamTimer);
stopRecording(true);
}
}
if (data.action === 'stop_dashcam_recording') {
if (isDashcamRecording) {
isDashcamRecording = false;
$('#dashcam-recording-ui').hide();
clearTimeout(dashcamRecordingTimeout);
clearInterval(dashcamTimer);
stopRecording(true);
}
}
if (data.action === 'cancel_rec_force') { if (data.action === 'cancel_rec_force') {
if (isRecording) { if (isRecording) {
// Force stop recording // Force stop recording
@ -129,6 +180,13 @@ $(document).ready(function () {
}, 1000); }, 1000);
stopRecording(); stopRecording();
} }
if (isDashcamRecording) {
isDashcamRecording = false;
$('#dashcam-recording-ui').hide();
clearTimeout(dashcamRecordingTimeout);
clearInterval(dashcamTimer);
stopRecording(true);
}
} }
// RECORDS SHOWING // RECORDS SHOWING
@ -138,16 +196,18 @@ $(document).ready(function () {
if (Array.isArray(data.recordData) && data.recordData.length > 0) { if (Array.isArray(data.recordData) && data.recordData.length > 0) {
$.each(data.recordData, function (index, record) { $.each(data.recordData, function (index, record) {
var recordType = record.recordtype || 'bodycam';
var recordIcon = recordType === 'dashcam' ? 'fa-car' : 'fa-video';
var camBox = $( var camBox = $(
` `
<div class="camBox"> <div class="camBox">
<div class="camInfo"> <div class="camInfo">
<div class="camTitle">${record.playername}<span class="camStreet"> [${record.street}]</span></div> <div class="camTitle">${record.playername}<span class="camStreet"> [${record.street}]</span></div>
<div class="camDesc">Date: ${record.date}</div> <div class="camDesc">${recordType.toUpperCase()} | Date: ${record.date}</div>
</div> </div>
<div class="camIcons"> <div class="camIcons">
<div class="camShow" data-stored="${record.videolink}"><i class="fa-solid fa-eye"></i></div> <div class="camShow" data-stored="${record.videolink}"><i class="fa-solid fa-eye"></i></div>
${data.isBoss ? `<div class="camDelete"><i class="fa-solid fa-trash"></i></div>` : ''} ${data.isBoss ? `<div class="camDelete" data-url="${record.videolink}"><i class="fa-solid fa-trash"></i></div>` : ''}
</div> </div>
</div> </div>
` `
@ -166,16 +226,18 @@ $(document).ready(function () {
$('.recInnerScroll').empty(); $('.recInnerScroll').empty();
if (Array.isArray(data.recordData) && data.recordData.length > 0) { if (Array.isArray(data.recordData) && data.recordData.length > 0) {
$.each(data.recordData, function (index, record) { $.each(data.recordData, function (index, record) {
var recordType = record.recordtype || 'bodycam';
var recordIcon = recordType === 'dashcam' ? 'fa-car' : 'fa-video';
var camBox = $( var camBox = $(
` `
<div class="camBox"> <div class="camBox">
<div class="camInfo"> <div class="camInfo">
<div class="camTitle">${record.playername}<span class="camStreet"> [${record.street}]</span></div> <div class="camTitle">${record.playername}<span class="camStreet"> [${record.street}]</span></div>
<div class="camDesc">Date: ${record.date}</div> <div class="camDesc">${recordType.toUpperCase()} | Date: ${record.date}</div>
</div> </div>
<div class="camIcons"> <div class="camIcons">
<div class="camShow" data-stored="${record.videolink}"><i class="fa-solid fa-eye"></i></div> <div class="camShow" data-stored="${record.videolink}"><i class="fa-solid fa-eye"></i></div>
${data.isBoss ? `<div class="camDelete"><i class="fa-solid fa-trash"></i></div>` : ''} ${data.isBoss ? `<div class="camDelete" data-url="${record.videolink}"><i class="fa-solid fa-trash"></i></div>` : ''}
</div> </div>
</div> </div>
` `
@ -196,7 +258,7 @@ $(document).ready(function () {
function updateVisibility(searchText) { function updateVisibility(searchText) {
$('.camBox').each(function () { $('.camBox').each(function () {
var camTitleText = $(this).find('.camTitle').text().toLowerCase(); var camTitleText = $(this).find('.camTitle').text().toLowerCase();
var camDescDate = $(this).find('.camDesc').text().trim().replace('Date: ', ''); var camDescDate = $(this).find('.camDesc').text().trim().replace(/.*Date: /, '');
if ((searchText === '' || camTitleText.includes(searchText)) && if ((searchText === '' || camTitleText.includes(searchText)) &&
($(this).css('display') !== 'none' || camDescDate === $('.selectedDate').val()) ($(this).css('display') !== 'none' || camDescDate === $('.selectedDate').val())
) { ) {
@ -220,7 +282,7 @@ $(document).ready(function () {
$('.selectedDate').on('change', function () { $('.selectedDate').on('change', function () {
var selectedDate = $(this).val(); var selectedDate = $(this).val();
$('.camBox').each(function () { $('.camBox').each(function () {
var camDescDate = $(this).find('.camDesc').text().trim().replace('Date: ', ''); var camDescDate = $(this).find('.camDesc').text().trim().replace(/.*Date: /, '');
if (selectedDate === '') { if (selectedDate === '') {
$(this).show(); $(this).show();
} else if (selectedDate === camDescDate) { } else if (selectedDate === camDescDate) {
@ -235,7 +297,7 @@ $(document).ready(function () {
$(document).on('click', '.camDelete', function () { $(document).on('click', '.camDelete', function () {
const camBox = $(this).closest('.camBox'); const camBox = $(this).closest('.camBox');
deleteUrl = camBox.find('.camShow').data('stored'); deleteUrl = $(this).data('url');
$('.askMain').fadeIn(); $('.askMain').fadeIn();
}); });
@ -287,7 +349,7 @@ let mediaRecorder;
let audioStream; let audioStream;
const canvasElement = document.querySelector('canvas'); const canvasElement = document.querySelector('canvas');
async function uploadBlob(videoBlob, hook, service) { async function uploadBlob(videoBlob, hook, service, isDashcam = false) {
$.post(`https://${GetParentResourceName()}/exitBodyCam`, '{}'); $.post(`https://${GetParentResourceName()}/exitBodyCam`, '{}');
const formData = new FormData(); const formData = new FormData();
try { try {
@ -306,7 +368,8 @@ async function uploadBlob(videoBlob, hook, service) {
} }
responseData = await response.json(); responseData = await response.json();
$.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({
vidurl: responseData.url vidurl: responseData.url,
isDashcam: isDashcam
})); }));
} else if (service === 'fivemerr') { } else if (service === 'fivemerr') {
formData.append('file', videoBlob, 'video.webm'); formData.append('file', videoBlob, 'video.webm');
@ -322,7 +385,8 @@ async function uploadBlob(videoBlob, hook, service) {
} }
responseData = await response.json(); responseData = await response.json();
$.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({
vidurl: responseData.url vidurl: responseData.url,
isDashcam: isDashcam
})); }));
} else if (service === 'discord') { } else if (service === 'discord') {
formData.append('file', videoBlob, 'video.webm'); formData.append('file', videoBlob, 'video.webm');
@ -335,7 +399,8 @@ async function uploadBlob(videoBlob, hook, service) {
} }
responseData = await response.json(); responseData = await response.json();
$.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({ $.post(`https://${GetParentResourceName()}/videoLog`, JSON.stringify({
vidurl: responseData.attachments[0].url vidurl: responseData.attachments[0].url,
isDashcam: isDashcam
})); }));
} }
} catch (error) { } catch (error) {
@ -353,15 +418,16 @@ async function startMicrophoneCapture() {
} }
} }
async function startRecording(hook, service) { async function startRecording(hook, service, recordTime, isDashcam = false) {
audioStream = await startMicrophoneCapture(); audioStream = await startMicrophoneCapture();
if (!isRecording){ if (!isRecording && !isDashcamRecording) {
if (audioStream) { if (audioStream) {
audioStream.getAudioTracks().forEach(track => track.stop()); audioStream.getAudioTracks().forEach(track => track.stop());
} }
return return;
} }
console.log('Video Recording Started');
console.log(isDashcam ? 'Dashcam Recording Started' : 'Bodycam Recording Started');
const gameView = gameview.createGameView(canvasElement); const gameView = gameview.createGameView(canvasElement);
const canvasStream = canvasElement.captureStream(30); const canvasStream = canvasElement.captureStream(30);
@ -379,7 +445,7 @@ async function startRecording(hook, service) {
mediaRecorder.onstop = async () => { mediaRecorder.onstop = async () => {
const videoBlob = new Blob(videoChunks, { type: 'video/webm' }); const videoBlob = new Blob(videoChunks, { type: 'video/webm' });
if (videoBlob.size > 0) { if (videoBlob.size > 0) {
uploadBlob(videoBlob, hook, service); uploadBlob(videoBlob, hook, service, isDashcam);
} }
if (audioStream) { if (audioStream) {
audioStream.getAudioTracks().forEach(track => track.stop()); audioStream.getAudioTracks().forEach(track => track.stop());
@ -387,8 +453,15 @@ async function startRecording(hook, service) {
}; };
} }
function stopRecording() { function stopRecording(isDashcam = false) {
if (mediaRecorder && mediaRecorder.state === 'recording') { if (mediaRecorder && mediaRecorder.state === 'recording') {
mediaRecorder.stop(); mediaRecorder.stop();
} }
}
if (isDashcam) {
isDashcamRecording = false;
$('#dashcam-recording-ui').hide();
} else {
isRecording = false;
}
}

View file

@ -448,4 +448,57 @@
color: rgba(255, 255, 255, 0.26); color: rgba(255, 255, 255, 0.26);
font-size: 3rem; font-size: 3rem;
font-family: "Fjalla One", sans-serif; font-family: "Fjalla One", sans-serif;
} }
/* Dashcam Recording UI */
#dashcam-recording-ui {
position: absolute;
top: 20px;
left: 20px;
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 15px;
border-radius: 5px;
font-family: "Play", sans-serif;
display: none;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
border: 1px solid rgba(255, 0, 0, 0.3);
min-width: 250px;
}
.dashcam-header {
display: flex;
align-items: center;
margin-bottom: 10px;
font-weight: bold;
font-size: 16px;
}
#dashcam-vehicle-info {
font-size: 14px;
margin-bottom: 5px;
color: #f0f0f0;
}
#dashcam-timer {
font-size: 20px;
font-weight: bold;
color: #ff3333;
text-align: center;
}
.dashcam-recording-indicator {
width: 12px;
height: 12px;
background-color: red;
border-radius: 50%;
display: inline-block;
margin-right: 10px;
animation: blink 1s infinite;
}
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}