Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"Потоковая передача аудиоданных","local":"потоковая-передача-аудиоданных","sections":[],"depth":1}"> | |
| <link href="/docs/audio-course/pr_201/ru/_app/immutable/assets/0.e3b0c442.css" rel="modulepreload"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/entry/start.09f2bcd2.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/scheduler.f7e1785c.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/singletons.81bb146a.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/index.279db187.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/paths.fd9a933e.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/entry/app.ea37f525.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/index.9f8f0838.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/nodes/0.e875dd2e.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/each.e59479a4.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/nodes/10.60e919f8.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/CodeBlock.b3510e34.js"> | |
| <link rel="modulepreload" href="/docs/audio-course/pr_201/ru/_app/immutable/chunks/EditOnGithub.5a9bb8c5.js"><!-- HEAD_svelte-u9bgzb_START --><meta name="hf:doc:metadata" content="{"title":"Потоковая передача аудиоданных","local":"потоковая-передача-аудиоданных","sections":[],"depth":1}"><!-- HEAD_svelte-u9bgzb_END --> <p></p> <h1 class="relative group"><a id="потоковая-передача-аудиоданных" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#потоковая-передача-аудиоданных"><span><svg class="" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg></span></a> <span>Потоковая передача аудиоданных</span></h1> <p data-svelte-h="svelte-kxri5f">Одной из самых больших проблем, возникающих при работе с аудиоданными, является их огромный размер. Одна минута несжатого аудиофайла CD-качества (44,1 кГц, 16 бит) | |
| занимает чуть более 5 МБ памяти. Как правило, набор аудиоданных содержат несколько часов записей.</p> <p data-svelte-h="svelte-kbnxfy">В предыдущих разделах мы использовали очень небольшое подмножество набора аудиоданных MINDS-14, однако типичные наборы аудиоданных гораздо больше. | |
| Например, <code>xs</code> (наименьшая) конфигурация <a href="https://huggingface.co/datasets/speechcolab/gigaspeech" rel="nofollow">GigaSpeech от SpeechColab</a> | |
| содержит всего 10 часов обучающих данных, но для их загрузки и подготовки требуется более 13 Гбайт дискового пространства. Что же | |
| произойдет, если мы захотим обучиться на более крупной части набора данных? Полная конфигурация <code>xl</code> того же набора данных содержит 10 000 часов | |
| тренировочных данных, что требует более 1 ТБ дискового пространства. Для большинства из нас это значительно превышает характеристики обычного | |
| жесткого диска. Нужно ли нам тратиться на покупку дополнительного хранилища? Или есть способ обучения на этих наборах данных без ограничения дискового пространства?</p> <p data-svelte-h="svelte-1sxggcv">🤗 Datasets приходит на помощь, предлагая [потоковый режим] (<a href="https://huggingface.co/docs/datasets/stream" rel="nofollow">https://huggingface.co/docs/datasets/stream</a>). Потоковая передача позволяет загружать данные постепенно, | |
| по мере того как мы итерируемся по набору данных. Вместо того чтобы загружать весь набор данных сразу, мы загружаем его по одному образцу за раз. | |
| Мы итеративно обращаемся к набору данных, загружая и подготавливая образцы на лету, когда это необходимо. Таким образом, мы всегда | |
| загружаем только те образцы, которые мы используем, а не те, которые мы не используем! | |
| Закончив работу с образцом, мы продолжаем итерацию по набору данных и загружаем следующий образец.</p> <p data-svelte-h="svelte-1mw7r3k">Потоковый режим имеет три основных преимущества перед загрузкой всего набора данных целиком:</p> <ul data-svelte-h="svelte-635716"><li>Дисковое пространство: образцы загружаются в память один за другим по мере итерации по набору данных. Поскольку данные не загружаются | |
| локально, то не требуется дисковое пространство, поэтому можно использовать наборы данных произвольного размера.</li> <li>Время загрузки и обработки: аудиоданные имеют большой объем и требуют значительного времени для загрузки и обработки. | |
| При потоковой передаче данных загрузка и обработка выполняются “на лету”, то есть вы можете начать использовать набор данных, как только | |
| будет готов первый образец.</li> <li>Простота экспериментов: вы можете провести эксперимент на нескольких образцах, чтобы проверить, работает ли ваш скрипт, без необходимости | |
| загружать весь набор данных.</li></ul> <p data-svelte-h="svelte-11lgss4">В режиме потоковой передачи данных есть одна оговорка. При загрузке полного набора данных без потоковой передачи как исходные данные, так и обработанные | |
| сохраняются локально на диске. Если мы захотим повторно использовать этот набор данных, мы можем напрямую загрузить обработанные данные с диска, | |
| минуя этапы загрузки и обработки. Следовательно, нам достаточно один раз выполнить операции загрузки и обработки, | |
| после чего мы можем повторно использовать подготовленные данные.</p> <p data-svelte-h="svelte-bkjl77">В потоковом режиме данные не загружаются на диск. Таким образом, ни загруженные, ни предварительно обработанные данные не кэшируются. | |
| Если мы хотим повторно использовать набор данных, необходимо повторить шаги потоковой передачи, при этом аудиофайлы должны быть загружены и обработаны на | |
| “на лету” заново. По этой причине рекомендуется загружать наборы данных, которые, скорее всего, будут использоваться многократно.</p> <p data-svelte-h="svelte-9n8tof">Как включить потоковый режим? Легко! Просто установите <code>streaming=True</code> при загрузке набора данных. Об остальном позаботятся:</p> <div class="code-block relative"><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->gigaspeech = load_dataset(<span class="hljs-string">"speechcolab/gigaspeech"</span>, <span class="hljs-string">"xs"</span>, streaming=<span class="hljs-literal">True</span>)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-sqxsjw">Подобно тому, как мы применяли шаги предварительной обработки к загруженному подмножеству MINDS-14, точно так же можно выполнить | |
| ту же самую предварительную обработку с потоковым набором данных.</p> <p data-svelte-h="svelte-r0v9bs">Единственное отличие заключается в том, что вы больше не можете обращаться к отдельным образцам, используя индексацию Python (т.е. <code>gigaspeech["train"][sample_idx]</code>). | |
| Вместо этого приходится выполнять итерации по набору данных. Вот как можно получить доступ к образцу при потоковой передаче набора данных:</p> <div class="code-block relative"><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START --><span class="hljs-built_in">next</span>(<span class="hljs-built_in">iter</span>(gigaspeech[<span class="hljs-string">"train"</span>]))<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1mvdyro"><strong>Output:</strong></p> <div class="code-block relative"><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->{ | |
| <span class="hljs-string">"segment_id"</span>: <span class="hljs-string">"YOU0000000315_S0000660"</span>, | |
| <span class="hljs-string">"speaker"</span>: <span class="hljs-string">"N/A"</span>, | |
| <span class="hljs-string">"text"</span>: <span class="hljs-string">"AS THEY'RE LEAVING <COMMA> CAN KASH PULL ZAHRA ASIDE REALLY QUICKLY <QUESTIONMARK>"</span>, | |
| <span class="hljs-string">"audio"</span>: { | |
| <span class="hljs-string">"path"</span>: <span class="hljs-string">"xs_chunks_0000/YOU0000000315_S0000660.wav"</span>, | |
| <span class="hljs-string">"array"</span>: <span class="hljs-built_in">array</span>( | |
| <span class="hljs-selector-attr">[0.0005188, 0.00085449, 0.00012207, ..., 0.00125122, 0.00076294, 0.00036621]</span> | |
| ), | |
| <span class="hljs-string">"sampling_rate"</span>: <span class="hljs-number">16000</span>, | |
| }, | |
| <span class="hljs-string">"begin_time"</span>: <span class="hljs-number">2941.89</span>, | |
| <span class="hljs-string">"end_time"</span>: <span class="hljs-number">2945.07</span>, | |
| <span class="hljs-string">"audio_id"</span>: <span class="hljs-string">"YOU0000000315"</span>, | |
| <span class="hljs-string">"title"</span>: <span class="hljs-string">"Return to Vasselheim | Critical Role: VOX MACHINA | Episode 43"</span>, | |
| <span class="hljs-string">"url"</span>: <span class="hljs-string">"https://www.youtube.com/watch?v=zr2n1fLVasU"</span>, | |
| <span class="hljs-string">"source"</span>: <span class="hljs-number">2</span>, | |
| <span class="hljs-string">"category"</span>: <span class="hljs-number">24</span>, | |
| <span class="hljs-string">"original_full_path"</span>: <span class="hljs-string">"audio/youtube/P0004/YOU0000000315.opus"</span>, | |
| }<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1hykw6v">Если вы хотите ознакомиться с несколькими образцами из большого набора данных, воспользуйтесь функцией <code>take()</code> для получения первых n элементов. Возьмем | |
| первые два образца из набора данных gigaspeech:</p> <div class="code-block relative"><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->gigaspeech_head = gigaspeech[<span class="hljs-string">"train"</span>].take(<span class="hljs-number">2</span>) | |
| <span class="hljs-built_in">list</span>(gigaspeech_head)<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-1mvdyro"><strong>Output:</strong></p> <div class="code-block relative"><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg class="" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg> <div class="absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0"><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent; "></div> Copied</div></button></div> <pre class=""><!-- HTML_TAG_START -->[ | |
| { | |
| <span class="hljs-string">"segment_id"</span>: <span class="hljs-string">"YOU0000000315_S0000660"</span>, | |
| <span class="hljs-string">"speaker"</span>: <span class="hljs-string">"N/A"</span>, | |
| <span class="hljs-string">"text"</span>: <span class="hljs-string">"AS THEY'RE LEAVING <COMMA> CAN KASH PULL ZAHRA ASIDE REALLY QUICKLY <QUESTIONMARK>"</span>, | |
| <span class="hljs-string">"audio"</span>: { | |
| <span class="hljs-string">"path"</span>: <span class="hljs-string">"xs_chunks_0000/YOU0000000315_S0000660.wav"</span>, | |
| <span class="hljs-string">"array"</span>: array( | |
| [ | |
| <span class="hljs-number">0.0005188</span>, | |
| <span class="hljs-number">0.00085449</span>, | |
| <span class="hljs-number">0.00012207</span>, | |
| ..., | |
| <span class="hljs-number">0.00125122</span>, | |
| <span class="hljs-number">0.00076294</span>, | |
| <span class="hljs-number">0.00036621</span>, | |
| ] | |
| ), | |
| <span class="hljs-string">"sampling_rate"</span>: <span class="hljs-number">16000</span>, | |
| }, | |
| <span class="hljs-string">"begin_time"</span>: <span class="hljs-number">2941.89</span>, | |
| <span class="hljs-string">"end_time"</span>: <span class="hljs-number">2945.07</span>, | |
| <span class="hljs-string">"audio_id"</span>: <span class="hljs-string">"YOU0000000315"</span>, | |
| <span class="hljs-string">"title"</span>: <span class="hljs-string">"Return to Vasselheim | Critical Role: VOX MACHINA | Episode 43"</span>, | |
| <span class="hljs-string">"url"</span>: <span class="hljs-string">"https://www.youtube.com/watch?v=zr2n1fLVasU"</span>, | |
| <span class="hljs-string">"source"</span>: <span class="hljs-number">2</span>, | |
| <span class="hljs-string">"category"</span>: <span class="hljs-number">24</span>, | |
| <span class="hljs-string">"original_full_path"</span>: <span class="hljs-string">"audio/youtube/P0004/YOU0000000315.opus"</span>, | |
| }, | |
| { | |
| <span class="hljs-string">"segment_id"</span>: <span class="hljs-string">"AUD0000001043_S0000775"</span>, | |
| <span class="hljs-string">"speaker"</span>: <span class="hljs-string">"N/A"</span>, | |
| <span class="hljs-string">"text"</span>: <span class="hljs-string">"SIX TOMATOES <PERIOD>"</span>, | |
| <span class="hljs-string">"audio"</span>: { | |
| <span class="hljs-string">"path"</span>: <span class="hljs-string">"xs_chunks_0000/AUD0000001043_S0000775.wav"</span>, | |
| <span class="hljs-string">"array"</span>: array( | |
| [ | |
| <span class="hljs-number">1.43432617</span>e-03, | |
| <span class="hljs-number">1.37329102</span>e-03, | |
| <span class="hljs-number">1.31225586</span>e-03, | |
| ..., | |
| <span class="hljs-number">-6.10351562</span>e-05, | |
| <span class="hljs-number">-1.22070312</span>e-04, | |
| <span class="hljs-number">-1.83105469</span>e-04, | |
| ] | |
| ), | |
| <span class="hljs-string">"sampling_rate"</span>: <span class="hljs-number">16000</span>, | |
| }, | |
| <span class="hljs-string">"begin_time"</span>: <span class="hljs-number">3673.96</span>, | |
| <span class="hljs-string">"end_time"</span>: <span class="hljs-number">3675.26</span>, | |
| <span class="hljs-string">"audio_id"</span>: <span class="hljs-string">"AUD0000001043"</span>, | |
| <span class="hljs-string">"title"</span>: <span class="hljs-string">"Asteroid of Fear"</span>, | |
| <span class="hljs-string">"url"</span>: <span class="hljs-string">"http//www.archive.org/download/asteroid_of_fear_1012_librivox/asteroid_of_fear_1012_librivox_64kb_mp3.zip"</span>, | |
| <span class="hljs-string">"source"</span>: <span class="hljs-number">0</span>, | |
| <span class="hljs-string">"category"</span>: <span class="hljs-number">28</span>, | |
| <span class="hljs-string">"original_full_path"</span>: <span class="hljs-string">"audio/audiobook/P0011/AUD0000001043.opus"</span>, | |
| }, | |
| ]<!-- HTML_TAG_END --></pre></div> <p data-svelte-h="svelte-yztf0w">Потоковый режим может вывести ваши исследования на новый уровень: вам не только доступны самые большие наборы данных, но вы | |
| можете легко оценивать системы на нескольких наборах данных за один раз, не заботясь о дисковом пространстве. По сравнению с оценкой | |
| на одном наборе данных, оценка на нескольких наборах дает более точную метрику обобщающих способностей | |
| системы распознавания речи (например, End-to-end Speech Benchmark (ESB)).</p> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/audio-transformers-course/blob/main/chapters/ru/chapter1/streaming.mdx" target="_blank"><span data-svelte-h="svelte-1kd6by1"><</span> <span data-svelte-h="svelte-x0xyl0">></span> <span data-svelte-h="svelte-1dajgef"><span class="underline ml-1.5">Update</span> on GitHub</span></a> <p></p> | |
| <script> | |
| { | |
| __sveltekit_2kx7xw = { | |
| assets: "/docs/audio-course/pr_201/ru", | |
| base: "/docs/audio-course/pr_201/ru", | |
| env: {} | |
| }; | |
| const element = document.currentScript.parentElement; | |
| const data = [null,null]; | |
| Promise.all([ | |
| import("/docs/audio-course/pr_201/ru/_app/immutable/entry/start.09f2bcd2.js"), | |
| import("/docs/audio-course/pr_201/ru/_app/immutable/entry/app.ea37f525.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 10], | |
| data, | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 26.7 kB
- Xet hash:
- 1052af04b6a9f5aec1b416291865788c53d15e6f656bb3f1407f5004adf787cd
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.