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
За замовчуванням звукові дані завантажуються повністю, але іноді корисно завантажувати їх фрагментами перед використанням. Це часто називають «потоковим завантаженням» (streaming).
Одна з переваг потокового завантаження звуку — менше споживання пам’яті під час виконання. Інша перевага полягає в тому, що, завантажуючи вміст потоково, наприклад, з HTTP URL, ви можете оновлювати його будь-коли, а також уникнути початкового завантаження.
Існує проєкт-приклад, що демонструє таке налаштування: https://github.com/defold/example-sound-streaming
Найпростіший спосіб використовувати потокове завантаження звуку — увімкнути налаштування sound.stream_enabled у game.project. Коли цю опцію ввімкнено, рушій почне завантажувати звуки потоково.
Примітка: якщо у вас одночасно завантажено багато звукових файлів, може знадобитися збільшити значення sound.stream_cache_size (див. нижче).
Також можна створити новий ресурс звукових даних і призначити його звуковому компоненту (sound component).
Для цього:
resource.create_sound_data().go.set()Нижче наведено фрагмент із проєкту-прикладу, у якому http.request() використовується для початкового отримання звукового файлу.
Для потокового завантаження вебсервер має обробляти HTTP-запити діапазонів і повертати код статусу 206. Якщо сервер ігнорує заголовок Range і повертає код статусу 200, наведений нижче приклад натомість створює звичайний ресурс без потокового завантаження з повної відповіді.
local function play_sound(self, hash)
go.set(self.component, "sound", hash) -- override the resource data on the component
sound.play(self.component) -- start playing the sound
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
-- Callback for the http response.
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
-- A partial resource enables streaming. filesize is the size of the
-- complete file, not only the returned range.
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
Для завантаження початкового фрагмента звукового файлу можна використовувати й інші способи. Важливо пам’ятати, що решта фрагментів завантажується через систему ресурсів та її постачальників ресурсів. У цьому прикладі ми додаємо нового постачальника файлів (HTTP), додаючи точку монтування Live Update за допомогою виклику liveupdate.add_mount().
Робочий приклад можна знайти тут: https://github.com/defold/example-sound-streaming.
-- See http_result() from above example
local function load_web_sound(base_url, relative_path)
local url = base_url .. "/" .. relative_path
local headers = {}
-- Request the initial part of the file
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)
-- once the mount is ready, we can start our request for downloading the first chunk
load_web_sound(self.base_url, self.filename)
end)
end
function final(self)
liveupdate.remove_mount("webmount")
end
Обсяг пам’яті, який звуки споживають під час виконання, регулюється налаштуванням sound.stream_cache_size у game.project. Обсяг завантажених звукових даних ніколи не перевищуватиме заданого обмеження.
Початковий фрагмент кожного звукового файлу не можна витіснити з кешу, і він займатиме місце в кеші, доки ресурс завантажений. Розмір початкового фрагмента регулюється налаштуванням sound.stream_preload_size у game.project.
Ви також можете керувати розміром кожного звукового фрагмента, змінюючи налаштування sound.stream_chunk_size у game.project. Це може допомогти ще більше зменшити розмір звукового кешу, якщо у вас одночасно завантажено багато звукових файлів. Звукові файли, менші за розмір звукового фрагмента, не завантажуються потоково, а якщо новий фрагмент не вміщується в кеш, найстаріший фрагмент витісняється
Загальний розмір кешу звукових фрагментів має перевищувати добуток кількості завантажених звукових файлів і розміру фрагмента потоку. Інакше ви ризикуєте витісняти нові фрагменти кожного кадру, і звуки не відтворюватимуться належним чином