This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Domyślnie dane dźwiękowe są wczytywane w całości, ale czasem korzystniejsze może być ładowanie ich partiami, jeszcze przed użyciem. Nazywa się to strumieniowaniem.
Jedną z korzyści strumieniowania dźwięku jest mniejsze zużycie pamięci w czasie działania. Inną jest to, że jeśli strumieniujesz treści np. z adresu HTTP, możesz je aktualizować w dowolnym momencie i uniknąć początkowego pobierania.
Istnieje przykładowy projekt demonstrujący to rozwiązanie: https://github.com/defold/example-sound-streaming
Najprostszym sposobem korzystania ze strumieniowania dźwięku jest włączenie ustawienia sound.stream_enabled w pliku game.project. Gdy ta opcja jest włączona, silnik zacznie strumieniować dźwięki.
Uwaga: jeśli jednocześnie załadowanych jest wiele plików dźwiękowych, może być konieczne zwiększenie wartości sound.stream_cache_size (zobacz niżej).
Możesz też utworzyć nowy zasób danych dźwięku i przypisać go do komponentu dźwięku.
Zrób to w ten sposób:
resource.create_sound_data().go.set()Poniżej znajduje się fragment przykładowego projektu, który używa http.request() do pobrania początkowej części pliku dźwiękowego.
Rzeczywiste strumieniowanie wymaga, aby serwer WWW respektował żądania zakresowe HTTP i zwracał status 206. Jeśli serwer zignoruje nagłówek Range i zwróci status 200, poniższy przykład utworzy zwykły, niestrumieniowany zasób z pełnej odpowiedzi.
local function play_sound(self, hash)
go.set(self.component, "sound", hash) -- zastąp dane zasobu na komponencie
sound.play(self.component) -- rozpocznij odtwarzanie dźwięku
end
local function parse_content_range(value)
if not value then
return nil
end
local rstart, rend, filesize = value:match("^bytes%s+(%d+)%-(%d+)/(%d+)$")
return tonumber(rstart), tonumber(rend), tonumber(filesize)
end
-- Funkcja zwrotna dla odpowiedzi HTTP.
local function http_result(self, _id, response)
if response.status ~= 200 and response.status ~= 206 then
return
end
local options = {
data = response.response,
}
if response.status == 206 then
local rstart, _, filesize = parse_content_range(response.headers["content-range"])
if rstart ~= 0 or not filesize then
print("Invalid Content-Range response")
return
end
-- Zasób częściowy włącza strumieniowanie. filesize jest rozmiarem
-- całego pliku, a nie tylko zwróconego zakresu.
if #response.response < filesize then
options.filesize = filesize
options.partial = true
end
end
local relative_path = self.filename
print("Creating resource", relative_path)
local resource_hash = resource.create_sound_data(relative_path, options)
play_sound(self, resource_hash)
end
local function load_web_sound(base_url, relative_path)
local url = base_url .. "/" .. relative_path
local headers = {}
headers['Range'] = string.format("bytes=%d-%d", 0, 16384-1)
http.request(url, "GET", http_result, headers, nil, { ignore_cache = true })
end
Początkową część pliku dźwiękowego możesz wczytać także innymi sposobami. Ważne jest to, że pozostałe części są ładowane przez system zasobów i jego dostawców zasobów. W tym przykładzie dodajemy nowego dostawcę plików (http), tworząc punkt montowania live update za pomocą liveupdate.add_mount().
Działający przykład znajdziesz w https://github.com/defold/example-sound-streaming.
-- Zobacz http_result() z powyższego przykładu
local function load_web_sound(base_url, relative_path)
local url = base_url .. "/" .. relative_path
local headers = {}
-- Zażądaj początkowej części pliku
headers['Range'] = string.format("bytes=%d-%d", 0, 16384-1)
http.request(url, "GET", http_result, headers, nil, { ignore_cache = true })
end
function init(self)
self.base_url = "http://my.server.com"
self.filename = "/path/to/sound.ogg"
liveupdate.add_mount("webmount", self.base_url, 100, function (_self, _name, _uri, _result)
-- gdy punkt montowania będzie gotowy, możemy rozpocząć pobieranie pierwszej części
load_web_sound(self.base_url, self.filename)
end)
end
function final(self)
liveupdate.remove_mount("webmount")
end
Ilość pamięci zużywanej przez dźwięki w czasie działania jest kontrolowana przez ustawienie sound.stream_cache_size w pliku game.project. Przy tym limicie wczytane dane dźwiękowe nigdy go nie przekroczą.
Początkowej części każdego pliku dźwiękowego nie można usunąć z pamięci podręcznej i będzie ona zajmować miejsce tak długo, jak zasoby pozostają załadowane. Rozmiar początkowej części jest kontrolowany przez ustawienie sound.stream_preload_size w pliku game.project.
Rozmiar każdego fragmentu dźwięku możesz też kontrolować, zmieniając ustawienie sound.stream_chunk_size w pliku game.project. Może to pomóc jeszcze bardziej zmniejszyć rozmiar pamięci podręcznej dźwięku, jeśli jednocześnie masz załadowanych wiele plików dźwiękowych. Pliki dźwiękowe mniejsze niż rozmiar fragmentu dźwięku nie są strumieniowane, a jeśli nowa część nie mieści się w pamięci podręcznej, usuwana jest najstarsza część.
Całkowity rozmiar pamięci podręcznej fragmentów dźwięku powinien być większy niż liczba załadowanych plików dźwiękowych pomnożona przez rozmiar fragmentu strumieniowania. W przeciwnym razie ryzykujesz usuwanie nowych części w każdej klatce i dźwięki nie będą odtwarzane poprawnie.