#stream #media #http-request #audio-stream #local-storage #audio

stream-download

一个用于将内容流式传输到本地基于文件缓存的库

14 个版本 (6 个重大更改)

0.7.2 2024 年 8 月 14 日
0.7.0 2024 年 7 月 28 日
0.5.1 2024 年 3 月 31 日
0.4.0 2023 年 12 月 3 日
0.3.0 2023 年 9 月 5 日

多媒体 类别中排名 5

Download history 113/week @ 2024-05-03 46/week @ 2024-05-10 64/week @ 2024-05-17 88/week @ 2024-05-24 133/week @ 2024-05-31 74/week @ 2024-06-07 111/week @ 2024-06-14 78/week @ 2024-06-21 77/week @ 2024-06-28 272/week @ 2024-07-05 89/week @ 2024-07-12 70/week @ 2024-07-19 458/week @ 2024-07-26 293/week @ 2024-08-02 218/week @ 2024-08-09 134/week @ 2024-08-16

每月下载 1,111
7 crates 中使用 7 (6 个直接使用)

MIT/Apache

92KB
1.5K SLoC

stream-download-rs

crates.io docs.rs Dependency Status license CI codecov GitHub repo size Lines of Code

stream-download 是一个从远程位置流式传输内容到本地缓存并用作 readseek 可用源的库。请求的内容将在后台下载,在下载完成之前允许读取或搜索操作。如果下载仍在进行中,搜索操作可能会导致流从请求的位置重新启动。这对于需要流式传输可能需要很长时间下载的大文件的媒体应用程序非常有用。

此库大量使用适配器模式,以允许使用可插拔的传输和存储实现。

安装

cargo add stream-download

功能

  • http - 添加了基于 HTTP 的 SourceStream 特性的实现(默认启用)。
  • reqwest - 启用使用 reqwest 通过 http 进行流式传输内容(默认启用)。
  • reqwest-native-tls - 启用 reqwest 的 native-tls 功能。同时启用 reqwest 功能。
  • reqwest-rustls - 启用 reqwest 的 rustls 功能。同时启用 reqwest 功能。
  • open-dal - 添加了一个使用 Apache OpenDAL 作为后端的 SourceStream 实现功能。
  • temp-storage - 添加基于文件的临时存储后端(默认启用)。

如果您想使用 https 流,则需要 reqwest-native-tlsreqwest-rustls 之一。

使用方法

use std::error::Error;
use std::io::Read;
use std::result::Result;

use stream_download::storage::temp::TempStorageProvider;
use stream_download::{Settings, StreamDownload};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut reader = StreamDownload::new_http(
        "https://some-cool-url.com/some-file.mp3".parse()?,
        TempStorageProvider::new(),
        Settings::default(),
    )
    .await?;

    let mut buf = Vec::new();
    reader.read_to_end(&mut buf)?;
    Ok(())
}

示例

请参阅示例

传输方式

传输方式实现了 SourceStream 接口。提供了两种类型的传输方式 - http 用于典型的基于 HTTP 的源和 open_dal,它更复杂,但支持大量服务。

默认情况下仅启用 http。您可以通过实现自己的 SourceStream 来提供自定义传输。

未知长度的流

例如独立歌曲或视频这样的资源具有有限长度,我们使用它来支持某些定位功能。无限流或那些没有已知长度的流仍然受到支持,但尝试从流的末尾进行定位将返回错误。这可能会影响某些尝试执行此类定位操作的音频或视频库。如果需要显式检查无限流,可以在事先检查流的内容长度。

use std::error::Error;
use std::io::Read;
use std::result::Result;

use stream_download::http::HttpStream;
use stream_download::http::reqwest::Client;
use stream_download::source::SourceStream;
use stream_download::storage::temp::TempStorageProvider;
use stream_download::{Settings, StreamDownload};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let stream =
        HttpStream::<Client>::create("https://some-cool-url.com/some-stream".parse()?).await?;
    let content_length = stream.content_length();
    let is_infinite = content_length.is_none();
    println!("Infinite stream = {is_infinite}");

    let mut reader =
        StreamDownload::from_stream(stream, TempStorageProvider::default(), Settings::default())
            .await?;

    let mut buf = [0; 256];
    reader.read_exact(&mut buf)?;
    Ok(())
}

Icecast/Shoutcast 流

如果您使用此库来处理 Icecast 流或其衍生物,请查看 icy-metadata 包。在存储库中有如何与 stream-download 一起使用的示例 在此处

存储

存储模块提供了自定义流如何在本地上缓存的方法。提供了内存和基于临时文件的预配置实现。通常,您会希望使用基于临时文件的存储以避免使用过多内存,但如果您知道流的大小很小或需要在只读文件系统上运行应用程序,则可能更喜欢基于内存的存储。

use std::error::Error;
use std::io::Read;
use std::result::Result;

use stream_download::storage::memory::MemoryStorageProvider;
use stream_download::{Settings, StreamDownload};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut reader = StreamDownload::new_http(
        "https://some-cool-url.com/some-file.mp3".parse()?,
        // buffer will be stored in memory instead of on disk
        MemoryStorageProvider,
        Settings::default(),
    )
    .await?;

    Ok(())
}

有界存储

当使用不需要支持定位的无界流时,如果流可能运行一段时间,通常不希望让底层缓存无限增长。在这种情况下,您可能想使用 有界存储。有界存储使用循环缓冲区,当缓冲区填满时将覆盖最旧的内容。

use std::error::Error;
use std::io::Read;
use std::num::NonZeroUsize;
use std::result::Result;

use stream_download::storage::bounded::BoundedStorageProvider;
use stream_download::storage::memory::MemoryStorageProvider;
use stream_download::{Settings, StreamDownload};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut reader = StreamDownload::new_http(
        "https://some-cool-url.com/some-file.mp3".parse()?,
        // use bounded storage to keep the underlying size from growing indefinitely
        BoundedStorageProvider::new(
            // you can use any other kind of storage provider here
            MemoryStorageProvider,
            // be liberal with the buffer size, you need to make sure it holds enough space to
            // prevent any out-of-bounds reads
            NonZeroUsize::new(512 * 1024).unwrap(),
        ),
        Settings::default(),
    )
    .await?;

    Ok(())
}

自适应存储

当您需要同时支持有限流和无界流时,您可能想使用 自适应存储。这是一个便利包装器,当流没有内容长度时将使用有界存储,当流返回内容长度时将使用无界存储。

use std::error::Error;
use std::io::Read;
use std::num::NonZeroUsize;
use std::result::Result;

use stream_download::storage::adaptive::AdaptiveStorageProvider;
use stream_download::storage::temp::TempStorageProvider;
use stream_download::{Settings, StreamDownload};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let mut reader = StreamDownload::new_http(
        "https://some-cool-url.com/some-file.mp3".parse()?,
        // use adaptive storage to keep the underlying size from growing indefinitely
        // when the content type is not known
        AdaptiveStorageProvider::new(
            // you can use any other kind of storage provider here
            TempStorageProvider::default(),
            // be liberal with the buffer size, you need to make sure it holds enough space to
            // prevent any out-of-bounds reads
            NonZeroUsize::new(512 * 1024).unwrap(),
        ),
        Settings::default(),
    )
    .await?;

    Ok(())
}

身份验证和其他自定义

如果您需要进行身份验证或更改其他设置,则可以自定义您的 HTTP 请求。

请参阅客户端选项以自定义 HTTP 客户端构建器。

请参阅自定义客户端以动态修改每个 HTTP 请求。

支持的 Rust 版本

当前 MSRV 是 1.75.0

依赖项

~7–21MB
~325K SLoC