ब्लॉग पर वापस
Tutorial9 मिनट पढ़ें

FiveM म्यूजिक और रेडियो प्लेयर स्क्रिप्ट्स: xSound और अधिक

इन-गेम सही तरीके से संगीत चलाएं। xSound, रेडियो प्लेयर ऐप्स, बूमबॉक्स प्रॉप्स और पार्टियों, बारों और कारों के लिए सर्वश्रेष्ठ FiveM ऑडियो स्क्रिप्ट्स।

Agency Scripts

Agency Scripts के संस्थापक और प्रमुख डेवलपर

रोलप्ले में कस्टम रेडियो क्यों महत्वपूर्ण है

म्यूजिक और रेडियो आवश्यक वातावरणीय तत्व हैं जो एक FiveM रोलप्ले सर्वर को जीवंत बनाते हैं। जबकि GTA V अपने रेडियो स्टेशनों के साथ आता है, कस्टम रेडियो सिस्टम सर्वर मालिकों को थीम्ड स्टेशन बनाने देते हैं जो उनकी कम्युनिटी पहचान से मेल खाते हैं, लाइव DJ सेट स्ट्रीम करते हैं, कम्युनिटी-क्यूरेटेड प्लेलिस्ट चलाते हैं, और यहां तक कि इन-कैरेक्टर न्यूज़ बुलेटिन प्रसारित करते हैं। एक अच्छी तरह से निर्मित म्यूजिक सिस्टम सरल ऑडियो प्लेबैक से आगे जाता है। यह एक ही वाहन में खिलाड़ियों के लिए सिंक्रनाइज़्ड सुनने के अनुभव प्रदान करता है, बूमबॉक्स और क्लब स्पीकर्स से स्पैटियल ऑडियो, व्यक्तिगत प्लेलिस्ट जो खिलाड़ी फोन ऐप के माध्यम से प्रबंधित कर सकते हैं, और नाइटक्लब रोलप्ले के लिए DJ बूथ इंटीग्रेशन। तकनीकी आधार NUI ऑडियो क्षमताओं पर निर्भर करता है, जो आपको FiveM क्लाइंट के भीतर ब्राउज़र-आधारित ऑडियो API की पूरी शक्ति का लाभ उठाने देते हैं।

ऑडियो आर्किटेक्चर और NUI एकीकरण

FiveM का NUI लेयर गेम क्लाइंट में एम्बेडेड क्रोमियम-आधारित ब्राउज़र चलाता है, जिसका अर्थ है कि आपके पास Web Audio API, HTML5 ऑडियो एलिमेंट्स, और यहां तक कि MediaSource API तक पहुंच है जो अनुकूल स्ट्रीमिंग के लिए है। वास्तुकला तीन घटकों में विभाजित है: Lua क्लाइंट स्क्रिप्ट गेम-वर्ल्ड इंटरैक्शन जैसे वाहन में प्रवेश या स्पीकर के पास जाना संभालती है, NUI HTML और JavaScript लेयर वास्तविक ऑडियो प्लेबैक और विज़ुअलाइज़ेशन प्रबंधित करती है, और सर्वर कई क्लाइंट्स के बीच सिंक्रोनाइज़्ड प्लेबैक स्टेट्स का समन्वय करता है। जब कोई खिलाड़ी वाहन में प्रवेश करता है, तो क्लाइंट स्क्रिप्ट वर्तमान स्टेशन को प्ले करना शुरू करने के लिए एक NUI संदेश भेजती है। NUI लेयर एक ऑडियो एलिमेंट बनाती है, स्रोत URL सेट करती है, और प्लेबैक शुरू करती है। वॉल्यूम नियंत्रण पूरी तरह से NUI लेयर में Web Audio API के GainNode का उपयोग करके चिकनी वॉल्यूम संक्रमण के साथ संभाले जाते हैं:

-- Client-side: Vehicle radio controller
local currentStation = nil
local radioActive = false

CreateThread(function()
    while true do
        Wait(500)
        local ped = PlayerPedId()

        if IsPedInAnyVehicle(ped, false) then
            local vehicle = GetVehiclePedIsIn(ped, false)

            if not radioActive then
                radioActive = true
                -- Disable default GTA radio
                SetVehicleRadioEnabled(vehicle, false)

                -- Load saved station preference
                local savedStation = LocalPlayer.state.radioStation or 'station_1'
                SetStation(savedStation)
            end
        elseif radioActive then
            radioActive = false
            SendNUIMessage({action = 'stopRadio'})
            currentStation = nil
        end
    end
end)

function SetStation(stationId)
    local station = Config.Stations[stationId]
    if not station then return end

    currentStation = stationId
    SendNUIMessage({
        action = 'playStation',
        url = station.url,
        name = station.name,
        volume = LocalPlayer.state.radioVolume or 0.5,
    })
end

NUI ऑडियो प्लेयर सेटअप

NUI साइड को एक मजबूत ऑडियो प्लेयर की आवश्यकता होती है जो स्ट्रीम कनेक्शंस, बफरिंग, त्रुटि पुनर्प्राप्ति, और वॉल्यूम प्रबंधन को संभाले। सरल HTML5 ऑडियो एलिमेंट्स के बजाय Web Audio API का उपयोग करें क्योंकि यह आपको ऑडियो रूटिंग पर नियंत्रण देता है, आवृत्ति डेटा से विज़ुअलाइज़ेशन बनाने की अनुमति देता है, और स्थानिक ऑडियो प्रोसेसिंग का समर्थन करता है। वॉल्यूम नियंत्रण के लिए GainNode और विज़ुअलाइज़ेशन डेटा के लिए AnalyserNode के साथ एक AudioContext बनाएं:

// NUI JavaScript: Audio engine
class RadioPlayer {
    constructor() {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
        this.gainNode = this.audioContext.createGain();
        this.analyser = this.audioContext.createAnalyser();
        this.analyser.fftSize = 256;

        this.gainNode.connect(this.analyser);
        this.analyser.connect(this.audioContext.destination);

        this.audio = new Audio();
        this.audio.crossOrigin = 'anonymous';
        this.source = null;
        this.isPlaying = false;
    }

    play(url, volume) {
        this.stop();
        this.audio = new Audio(url);
        this.audio.crossOrigin = 'anonymous';
        this.audio.volume = 1.0;

        this.source = this.audioContext.createMediaElementSource(this.audio);
        this.source.connect(this.gainNode);
        this.gainNode.gain.value = volume;

        this.audio.play().then(() => {
            this.isPlaying = true;
        }).catch(err => {
            console.error('Radio playback failed:', err);
            setTimeout(() => this.play(url, volume), 3000);
        });
    }

    stop() {
        if (this.audio) {
            this.audio.pause();
            this.audio.src = '';
            this.isPlaying = false;
        }
    }

    setVolume(vol) {
        this.gainNode.gain.linearRampToValueAtTime(
            vol, this.audioContext.currentTime + 0.1
        );
    }

    getFrequencyData() {
        const data = new Uint8Array(this.analyser.frequencyBinCount);
        this.analyser.getByteFrequencyData(data);
        return data;
    }
}

const radio = new RadioPlayer();

स्टेशन कॉन्फ़िगरेशन और स्ट्रीमिंग

अपने रेडियो स्टेशनों को स्ट्रीम URL, मेटाडेटा, और शैली श्रेणियों के साथ परिभाषित करें। अधिकांश कस्टम FiveM रेडियो सिस्टम इंटरनेट रेडियो स्ट्रीम का उपयोग MP3 या AAC प्रारूप में करते हैं क्योंकि वे व्यापक रूप से समर्थित और सेटअप में आसान हैं। आप पूर्ण नियंत्रण के लिए अपना Icecast या Shoutcast सर्वर होस्ट कर सकते हैं, या सार्वजनिक रेडियो स्ट्रीम URL का उपयोग कर सकते हैं। प्रत्येक स्टेशन के लिए स्ट्रीम URL, डिस्प्ले नाम, शैली टैग, और वैकल्पिक रूप से UI के लिए लोगो छवि संग्रहीत करें। YouTube और SoundCloud URL के लिए प्रॉक्सी सेवाओं के माध्यम से समर्थन जोड़ने पर विचार करें, हालांकि सेवा की शर्तों और कॉपीराइट प्रतिबंधों का ध्यान रखें। लाइव DJ कार्यक्षमता के लिए, उन सेवाओं के साथ एकीकरण करें जो RTMP-से-HTTP स्ट्रीम रूपांतरण प्रदान करती हैं ताकि DJs OBS या समान सॉफ़्टवेयर का उपयोग करके प्रसारण कर सकें:

Config.Stations = {
    ['station_1'] = {
        name = 'Agency Radio',
        genre = 'Hip Hop',
        url = 'https://stream.example.com/hiphop',
        logo = 'station_hiphop.webp',
        description = 'The freshest beats in Los Santos',
    },
    ['station_2'] = {
        name = 'LS Rock Radio',
        genre = 'Rock',
        url = 'https://stream.example.com/rock',
        logo = 'station_rock.webp',
        description = 'Classic and modern rock anthems',
    },
    ['station_3'] = {
        name = 'Vinewood Lounge',
        genre = 'Jazz / Lofi',
        url = 'https://stream.example.com/lofi',
        logo = 'station_lofi.webp',
        description = 'Smooth vibes for the night drive',
    },
    ['station_live'] = {
        name = 'Live DJ',
        genre = 'Live',
        url = 'https://stream.example.com/live',
        logo = 'station_live.webp',
        description = 'Live DJ sets from the community',
        isLive = true,
    },
}

सिंक्ड वाहन रेडियो

जब एक ही वाहन में कई खिलाड़ी सवार होते हैं, तो उन्हें सभी को एक ही रेडियो स्टेशन सुनना चाहिए। इसके लिए सर्वर-साइड समन्वय की आवश्यकता होती है, जैसे कि स्टेट बैग्स या नेटवर्केड इवेंट्स के माध्यम से। जब ड्राइवर स्टेशन बदलता है, तो सर्वर सभी यात्रियों को नया स्टेशन प्रसारित करता है। कुशल सिंक्रनाइज़ेशन के लिए FiveM के स्टेट बैग सिस्टम का उपयोग करें क्योंकि यह नेटवर्क प्रतिकृति को स्वचालित रूप से संभालता है बिना मैनुअल इवेंट प्रबंधन के। स्टेशन को वाहन इकाई के स्टेट बैग पर सेट करें ताकि कोई भी खिलाड़ी वाहन में प्रवेश करते ही वर्तमान स्टेशन प्राप्त कर सके। किनारों के मामलों को संभालें जैसे कि यात्री वाहन में प्रवेश करते हैं जिसमें पहले से स्टेशन चल रहा है, ड्राइवर छोड़ देता है जबकि यात्री बने रहते हैं, और यदि आप गैर-ड्राइवर नियंत्रण की अनुमति देते हैं तो यात्रियों द्वारा विरोधाभासी स्टेशन परिवर्तन:

-- Server-side: Sync radio state via state bags
RegisterNetEvent('radio:server:setStation', function(vehicleNet, stationId)
    local src = source
    local vehicle = NetworkGetEntityFromNetworkId(vehicleNet)
    if not DoesEntityExist(vehicle) then return end

    -- Verify player is the driver
    local ped = GetPlayerPed(src)
    if GetPedInVehicleSeat(vehicle, -1) ~= ped then return end

    -- Set station on vehicle state bag
    Entity(vehicle).state:set('radioStation', stationId, true)
end)

-- Client-side: Listen for state bag changes
AddStateBagChangeHandler('radioStation', nil, function(bagName, key, value)
    if not value then return end
    local entity = GetEntityFromStateBagName(bagName)
    if not DoesEntityExist(entity) then return end

    local ped = PlayerPedId()
    if not IsPedInVehicle(ped, entity, false) then return end

    SetStation(value)
end)

स्पैटियल ऑडियो और बूमबॉक्स सिस्टम

स्पैटियल ऑडियो एक ऐसी परत जोड़ता है जो फ्लैट ऑडियो प्लेबैक से मेल नहीं खा सकती। बूमबॉक्स, क्लब स्पीकर, और कार स्टीरियो को ऐसी ध्वनि उत्सर्जित करनी चाहिए जो दूरी के साथ फीकी हो और स्रोत के सापेक्ष श्रोता की स्थिति के आधार पर पैन हो। FiveM मूल ऑडियो फ़ंक्शन प्रदान करता है जैसे PlaySoundFromCoord सरल स्थानिक ध्वनियों के लिए, लेकिन स्ट्रीमिंग ऑडियो के लिए आपको NUI लेयर में दूरी-आधारित वॉल्यूम स्केलिंग लागू करनी होगी। हर फ्रेम खिलाड़ी और ऑडियो स्रोत के बीच दूरी की गणना करें, फिर उस दूरी को वॉल्यूम कर्व पर मैप करें। यथार्थवादी ध्वनि क्षय के लिए इनवर्स-स्क्वायर फालऑफ का उपयोग करें, जिसमें कॉन्फ़िगर करने योग्य न्यूनतम और अधिकतम सुनने की दूरी हो। बूमबॉक्स के लिए जिन्हें खिलाड़ी दुनिया में रख सकते हैं, एक डिप्लॉयबल आइटम बनाएं जो खिलाड़ी के स्थान पर एक प्रॉप स्पॉन करता है और इसे ऑडियो स्रोत के रूप में रजिस्टर करता है। रेंज के भीतर अन्य खिलाड़ी स्वचालित रूप से संगीत सुनेंगे, उनके बूमबॉक्स प्रॉप से दूरी के आधार पर वॉल्यूम स्केलिंग के साथ।

प्लेयर प्लेलिस्ट और फोन इंटीग्रेशन

खिलाड़ियों को उनके संगीत अनुभव पर व्यक्तिगत नियंत्रण दें, एक प्लेलिस्ट सिस्टम के माध्यम से जो आपके सर्वर के फोन रिसोर्स के साथ एकीकृत हो। खिलाड़ी URL जोड़कर कस्टम प्लेलिस्ट बना सकें, गानों को ड्रैग-एंड-ड्रॉप से पुनःक्रमित करें, प्लेलिस्ट को शफल या रिपीट सेट करें, और अन्य खिलाड़ियों के साथ प्लेलिस्ट साझा करें। प्लेलिस्ट को डेटाबेस में खिलाड़ी के पहचानकर्ता से लिंक करके स्टोर करें ताकि वे सत्रों के बीच बनी रहें। फोन ऐप इंटरफ़ेस वर्तमान में चल रहे ट्रैक को कलाकार और शीर्षक मेटाडेटा के साथ दिखाए, प्लेबैक नियंत्रण जैसे प्ले, पॉज़, स्किप, और पिछला, वॉल्यूम स्लाइडर, और सहेजी गई प्लेलिस्ट की सूची। जब खिलाड़ी वाहन में हो, तो फोन प्लेयर ऑडियो को वाहन के रेडियो सिस्टम के माध्यम से स्वचालित रूप से रूट करे ताकि यात्री संगीत सुन सकें। पैदल चलते समय जब ईयरबड्स आइटम के रूप में पहने हों, तो संगीत निजी रूप से चलता है और एक छोटा ईयरफोन आइकन अन्य खिलाड़ियों को दिखाता है कि चरित्र संगीत सुन रहा है बिना इसे दूसरों को सुनाई दिए।

विज़ुअलाइज़र और UI डिज़ाइन

एक संगीत प्लेयर UI को जीवंत और ऑडियो के प्रति उत्तरदायी महसूस करना चाहिए। Web Audio API से AnalyserNode का उपयोग करें ताकि वास्तविक समय में आवृत्ति डेटा निकाला जा सके और एक ऑडियो विज़ुअलाइज़र प्रस्तुत किया जा सके। बार विज़ुअलाइज़र, वेवफ़ॉर्म डिस्प्ले, और वृत्ताकार स्पेक्ट्रम एनालाइज़र सभी आपके UI सौंदर्यशास्त्र के आधार पर अच्छी तरह काम करते हैं। प्रदर्शन के लिए विज़ुअलाइज़र को कैनवास एलिमेंट का उपयोग करके प्रस्तुत करें, जटिलता के आधार पर 30 या 60 फ्रेम प्रति सेकंड पर अपडेट करें। रेडियो UI स्वयं न्यूनतम और गैर-हस्तक्षेपकारी होना चाहिए, स्क्रीन के कोने में एक छोटा विजेट के रूप में दिखाई देना चाहिए जो वर्तमान स्टेशन का नाम, यदि उपलब्ध हो तो स्ट्रीम मेटाडेटा से ट्रैक शीर्षक, और बुनियादी प्लेबैक नियंत्रण दिखाता है। जब खिलाड़ी पूर्ण रेडियो मेनू खोलता है स्टेशन बदलने के लिए, उपलब्ध स्टेशनों की ग्रिड या सूची उनके लोगो, शैलियों, और श्रोता गणना के साथ दिखाएं। उन सर्वरों के लिए एक खोज बार शामिल करें जिनके पास कई स्टेशन हैं और एक पसंदीदा प्रणाली ताकि खिलाड़ी अपनी पसंदीदा स्टेशनों तक जल्दी पहुंच सकें बिना पूरी सूची में स्क्रॉल किए।

प्रदर्शन विचार

ऑडियो स्ट्रीमिंग बैंडविड्थ और क्लाइंट संसाधनों का उपभोग करता है, इसलिए अपनी कार्यान्वयन को सावधानी से अनुकूलित करें। मेमोरी लीक और CPU स्पाइक्स को रोकने के लिए प्रति क्लाइंट एक साथ ऑडियो स्ट्रीम की संख्या सीमित करें। जब कोई खिलाड़ी वाहन में नहीं होता और उसके पास कोई बूमबॉक्स नहीं होता, तो ऑडियो संदर्भ को पूरी तरह से नष्ट करें बजाय केवल उसे रोकने के। कई बूमबॉक्स से स्थानिक ऑडियो के लिए, केवल सुनने की सीमा के भीतर स्रोतों के लिए ऑडियो स्ट्रीम बनाएं और जैसे-जैसे स्रोत सीमा से बाहर जाते हैं स्ट्रीम साफ करें। परिवेश पृष्ठभूमि संगीत के लिए कम बिटरेट स्ट्रीम का उपयोग करें और प्राथमिक सुनने के अनुभव के लिए उच्च गुणवत्ता वाली स्ट्रीम सुरक्षित रखें। सर्वर पक्ष पर, स्ट्रीम URL सीधे इवेंट्स में भेजने से बचें क्योंकि उन्हें इंटरसेप्ट और दुरुपयोग किया जा सकता है। इसके बजाय, एक कॉलबैक सिस्टम का उपयोग करें जहां क्लाइंट किसी विशिष्ट स्टेशन ID के लिए स्ट्रीम URL का अनुरोध करता है और सर्वर समय-सीमित साइन किए गए URL के साथ जवाब देता है। क्लाइंट-रिपोर्ट किए गए प्लेबैक त्रुटियों की निगरानी करें और नेटवर्क समस्याओं के कारण गिरने वाली स्ट्रीम को स्वचालित रूप से पुनः कनेक्ट करें, संघर्षरत स्ट्रीम सर्वर को हानि पहुंचाने से बचाने के लिए घातीय बैकऑफ के साथ।

शुरू करने के लिए तैयार?

हमारी शॉप से स्क्रिप्ट लें, या सपोर्ट, अपडेट और आगे आने वाली चीज़ों की झलक के लिए Discord से जुड़ें।