Datachain

AudioFile

AudioFile extends File and provides additional methods for working with audio files.

AudioFile instances are created when a DataChain is initialized from storage with the type="audio" parameter:

import datachain as dc

chain = dc.read_storage("s3://bucket-name/", type="audio")

There are additional models for working with audio files:

  • AudioFragment - represents a fragment of an audio file.

These are virtual models that do not create physical files. Instead, they are used to represent the data in the AudioFile these models are referring to. If you need to save the data, you can use the save method of these models, allowing you to save data locally or upload it to a storage service.

For a complete example of audio processing with DataChain, see Audio-to-Text with Whisper - a speech recognition pipeline that uses AudioFile, AudioFragment, and Audio to chunk audio files and transcribe them.

AudioFile

AudioFile(**kwargs)

Bases: File

A data model for handling audio files.

This model inherits from the File model and provides additional functionality for reading audio files, extracting audio fragments, and splitting audio into fragments.

Source code in datachain/lib/file.py
327
328
329
330
331
332
def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self._catalog = None
    self._caching_enabled: bool = False
    self._download_cb: Callback = DEFAULT_CALLBACK
    self._fs_path_cache: tuple[str, str, str] | None = None

get_fragment

get_fragment(start: float, end: float) -> AudioFragment

Returns an audio fragment from the specified time range. It does not download the file, neither it actually extracts the fragment. It returns a Model representing the audio fragment, which can be used to read or save it later.

Parameters:

  • start (float) –

    The start time of the fragment in seconds.

  • end (float) –

    The end time of the fragment in seconds.

Returns:

  • AudioFragment ( AudioFragment ) –

    A Model representing the audio fragment.

Source code in datachain/lib/file.py
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
def get_fragment(self, start: float, end: float) -> "AudioFragment":
    """
    Returns an audio fragment from the specified time range. It does not
    download the file, neither it actually extracts the fragment. It returns
    a Model representing the audio fragment, which can be used to read or save
    it later.

    Args:
        start (float): The start time of the fragment in seconds.
        end (float): The end time of the fragment in seconds.

    Returns:
        AudioFragment: A Model representing the audio fragment.
    """
    if start < 0 or end < 0 or start >= end:
        raise ValueError(
            f"Can't get audio fragment for '{self.path}', "
            f"invalid time range: ({start:.3f}, {end:.3f})"
        )

    return AudioFragment(audio=self, start=start, end=end)

get_fragments

get_fragments(duration: float, start: float = 0, end: float | None = None) -> Iterator[AudioFragment]

Splits the audio into multiple fragments of a specified duration.

Parameters:

  • duration (float) –

    The duration of each audio fragment in seconds.

  • start (float, default: 0 ) –

    The starting time in seconds (default: 0).

  • end (float, default: None ) –

    The ending time in seconds. If None, the entire remaining audio is processed (default: None).

Returns:

Note

If end is not specified, number of samples will be taken from the audio file, this means audio metadata needs to be read.

Source code in datachain/lib/file.py
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
def get_fragments(
    self,
    duration: float,
    start: float = 0,
    end: float | None = None,
) -> "Iterator[AudioFragment]":
    """
    Splits the audio into multiple fragments of a specified duration.

    Args:
        duration (float): The duration of each audio fragment in seconds.
        start (float): The starting time in seconds (default: 0).
        end (float, optional): The ending time in seconds. If None, the entire
                               remaining audio is processed (default: None).

    Returns:
        Iterator[AudioFragment]: An iterator yielding audio fragments.

    Note:
        If end is not specified, number of samples will be taken from the
        audio file, this means audio metadata needs to be read.
    """
    if duration <= 0:
        raise ValueError("duration must be a positive float")
    if start < 0:
        raise ValueError("start must be a non-negative float")

    if end is None:
        end = self.get_info().duration

    if end < 0:
        raise ValueError("end must be a non-negative float")
    if start >= end:
        raise ValueError("start must be less than end")

    while start < end:
        yield self.get_fragment(start, min(start + duration, end))
        start += duration

get_info

get_info() -> Audio

Retrieves metadata and information about the audio file.

With prefetch and cache off, reads only the parts of the file it needs.

Returns:

  • Audio ( Audio ) –

    A Model containing audio metadata such as duration, sample rate, channels, and codec details.

Source code in datachain/lib/file.py
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
def get_info(self) -> "Audio":
    """
    Retrieves metadata and information about the audio file.

    With prefetch and cache off, reads only the parts of the file it needs.

    Returns:
        Audio: A Model containing audio metadata such as duration,
               sample rate, channels, and codec details.
    """
    from .audio import audio_info

    return audio_info(self)

save

save(destination: str, format: str | None = None, start: float = 0, end: float | None = None, client_config: dict | None = None, *, content_type: str | None = None, content_disposition: str | None = None, cache_control: str | None = None, content_encoding: str | None = None, metadata: dict[str, str] | None = None, write_options: dict[str, Any] | None = None) -> AudioFile

Save audio file or extract fragment to specified format.

If destination is a remote path, the audio file will be uploaded to remote storage.

Parameters:

  • destination (str) –

    Output directory path or URI (e.g. s3://…, gs://…).

  • format (str | None, default: None ) –

    Output format ('wav', 'mp3', etc). Defaults to source format.

  • start (float, default: 0 ) –

    Start time in seconds (>= 0). Defaults to 0.

  • end (float | None, default: None ) –

    End time in seconds. If None, extracts to end of file.

  • client_config (dict | None, default: None ) –

    Optional client configuration.

  • content_type (str | None, default: None ) –

    Content-Type to set on the written object.

  • content_disposition (str | None, default: None ) –

    Content-Disposition to set on the object.

  • cache_control (str | None, default: None ) –

    Cache-Control to set on the object.

  • content_encoding (str | None, default: None ) –

    Content-Encoding to set on the object.

  • metadata (dict[str, str] | None, default: None ) –

    Custom key/value metadata to attach to the object.

  • write_options (dict[str, Any] | None, default: None ) –

    Raw, backend-native write kwargs merged after the normalized fields above.

Returns:

  • AudioFile ( AudioFile ) –

    New audio file with format conversion/extraction applied.

Examples:

audio.save("/path", "mp3") # Entire file to MP3 audio.save("s3://bucket/path", "wav", start=2.5) # From 2.5s to end as WAV audio.save("/path", "flac", start=1, end=3) # 1-3s fragment as FLAC

Source code in datachain/lib/file.py
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
def save(  # type: ignore[override]
    self,
    destination: str,
    format: str | None = None,
    start: float = 0,
    end: float | None = None,
    client_config: dict | None = None,
    *,
    content_type: str | None = None,
    content_disposition: str | None = None,
    cache_control: str | None = None,
    content_encoding: str | None = None,
    metadata: dict[str, str] | None = None,
    write_options: dict[str, Any] | None = None,
) -> "AudioFile":
    """Save audio file or extract fragment to specified format.

    If ``destination`` is a remote path, the audio file will be uploaded
    to remote storage.

    Args:
        destination: Output directory path or URI (e.g. ``s3://…``, ``gs://…``).
        format: Output format ('wav', 'mp3', etc). Defaults to source format.
        start: Start time in seconds (>= 0). Defaults to 0.
        end: End time in seconds. If None, extracts to end of file.
        client_config: Optional client configuration.
        content_type: ``Content-Type`` to set on the written object.
        content_disposition: ``Content-Disposition`` to set on the object.
        cache_control: ``Cache-Control`` to set on the object.
        content_encoding: ``Content-Encoding`` to set on the object.
        metadata: Custom key/value metadata to attach to the object.
        write_options: Raw, backend-native write kwargs merged after the
            normalized fields above.

    Returns:
        AudioFile: New audio file with format conversion/extraction applied.

    Examples:
        audio.save("/path", "mp3")                        # Entire file to MP3
        audio.save("s3://bucket/path", "wav", start=2.5)  # From 2.5s to end as WAV
        audio.save("/path", "flac", start=1, end=3)       # 1-3s fragment as FLAC
    """
    if self._catalog is None:
        raise RuntimeError("Cannot save file: catalog is not set")

    from .audio import save_audio

    return save_audio(
        self,
        destination,
        format,
        start,
        end,
        client_config,
        write_config=WriteConfig(
            content_type=content_type,
            content_disposition=content_disposition,
            cache_control=cache_control,
            content_encoding=content_encoding,
            metadata=metadata,
            write_options=write_options,
        ),
    )

AudioFragment

Bases: DataModel

A data model for representing an audio fragment.

This model represents a specific fragment within an audio file with defined start and end times. It allows access to individual fragments and provides functionality for reading and saving audio fragments as separate audio files.

Attributes:

  • audio (AudioFile) –

    The audio file containing the audio fragment.

  • start (float) –

    The starting time of the audio fragment in seconds.

  • end (float) –

    The ending time of the audio fragment in seconds.

get_np

get_np() -> tuple[ndarray, int]

Returns the audio fragment as a NumPy array with sample rate.

Returns:

  • tuple[ndarray, int] –

    tuple[ndarray, int]: A tuple containing the audio data as a NumPy array and the sample rate.

Source code in datachain/lib/file.py
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
def get_np(self) -> tuple["ndarray", int]:
    """
    Returns the audio fragment as a NumPy array with sample rate.

    Returns:
        tuple[ndarray, int]: A tuple containing the audio data as a NumPy array
                           and the sample rate.
    """
    from .audio import audio_to_np

    duration = self.end - self.start
    return audio_to_np(self.audio, self.start, duration)

read_bytes

read_bytes(format: str = 'wav') -> bytes

Returns the audio fragment as audio bytes.

Parameters:

  • format (str, default: 'wav' ) –

    The desired audio format (e.g., 'wav', 'mp3'). Defaults to 'wav'.

Returns:

  • bytes ( bytes ) –

    The encoded audio fragment as bytes.

Source code in datachain/lib/file.py
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
def read_bytes(self, format: str = "wav") -> bytes:
    """
    Returns the audio fragment as audio bytes.

    Args:
        format (str): The desired audio format (e.g., 'wav', 'mp3').
                     Defaults to 'wav'.

    Returns:
        bytes: The encoded audio fragment as bytes.
    """
    from .audio import audio_to_bytes

    duration = self.end - self.start
    return audio_to_bytes(self.audio, format, self.start, duration)

save

save(destination: str, format: str | None = None, client_config: dict | None = None, *, content_type: str | None = None, content_disposition: str | None = None, cache_control: str | None = None, content_encoding: str | None = None, metadata: dict[str, str] | None = None, write_options: dict[str, Any] | None = None) -> AudioFile

Saves the audio fragment as a new audio file.

If destination is a remote path, the audio file will be uploaded to remote storage.

Parameters:

  • destination (str) –

    Output directory path or URI (e.g. s3://…, gs://…).

  • format (str | None, default: None ) –

    Output audio format (e.g., 'wav', 'mp3'). If None, inferred from the file extension.

  • client_config (dict | None, default: None ) –

    Optional client configuration (e.g. credentials).

  • content_type (str | None, default: None ) –

    Content-Type to set on the written object.

  • content_disposition (str | None, default: None ) –

    Content-Disposition to set on the object.

  • cache_control (str | None, default: None ) –

    Cache-Control to set on the object.

  • content_encoding (str | None, default: None ) –

    Content-Encoding to set on the object.

  • metadata (dict[str, str] | None, default: None ) –

    Custom key/value metadata to attach to the object.

  • write_options (dict[str, Any] | None, default: None ) –

    Raw, backend-native write kwargs merged after the normalized fields above.

Returns:

  • AudioFile ( AudioFile ) –

    A Model representing the saved audio file.

Source code in datachain/lib/file.py
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
def save(
    self,
    destination: str,
    format: str | None = None,
    client_config: dict | None = None,
    *,
    content_type: str | None = None,
    content_disposition: str | None = None,
    cache_control: str | None = None,
    content_encoding: str | None = None,
    metadata: dict[str, str] | None = None,
    write_options: dict[str, Any] | None = None,
) -> "AudioFile":
    """
    Saves the audio fragment as a new audio file.

    If ``destination`` is a remote path, the audio file will be uploaded
    to remote storage.

    Args:
        destination: Output directory path or URI (e.g. ``s3://…``, ``gs://…``).
        format: Output audio format (e.g., 'wav', 'mp3').
                If None, inferred from the file extension.
        client_config: Optional client configuration (e.g. credentials).
        content_type: ``Content-Type`` to set on the written object.
        content_disposition: ``Content-Disposition`` to set on the object.
        cache_control: ``Cache-Control`` to set on the object.
        content_encoding: ``Content-Encoding`` to set on the object.
        metadata: Custom key/value metadata to attach to the object.
        write_options: Raw, backend-native write kwargs merged after the
            normalized fields above.

    Returns:
        AudioFile: A Model representing the saved audio file.
    """
    from .audio import save_audio

    return save_audio(
        self.audio,
        destination,
        format,
        self.start,
        self.end,
        client_config=client_config,
        write_config=WriteConfig(
            content_type=content_type,
            content_disposition=content_disposition,
            cache_control=cache_control,
            content_encoding=content_encoding,
            metadata=metadata,
            write_options=write_options,
        ),
    )

Audio

Bases: DataModel

A data model representing metadata for an audio file.

Attributes:

  • sample_rate (int) –

    The sample rate of the audio (samples per second). Defaults to -1 if unknown.

  • channels (int) –

    The number of audio channels. Defaults to -1 if unknown.

  • duration (float) –

    The total duration of the audio in seconds. Defaults to -1.0 if unknown.

  • samples (int) –

    The total number of samples in the audio. Defaults to -1 if unknown.

  • format (str) –

    The format of the audio file (e.g., 'wav', 'mp3'). Defaults to an empty string.

  • codec (str) –

    The codec used for encoding the audio. Defaults to an empty string.

  • bit_rate (int) –

    The bit rate of the audio in bits per second. Defaults to -1 if unknown.

get_channel_name staticmethod

get_channel_name(num_channels: int, channel_idx: int) -> str

Map channel index to meaningful name based on common audio formats

Source code in datachain/lib/file.py
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
@staticmethod
def get_channel_name(num_channels: int, channel_idx: int) -> str:
    """Map channel index to meaningful name based on common audio formats"""
    channel_mappings = {
        1: ["Mono"],
        2: ["Left", "Right"],
        4: ["W", "X", "Y", "Z"],  # First-order Ambisonics
        6: ["FL", "FR", "FC", "LFE", "BL", "BR"],  # 5.1 surround
        8: ["FL", "FR", "FC", "LFE", "BL", "BR", "SL", "SR"],  # 7.1 surround
    }

    if num_channels in channel_mappings:
        channels = channel_mappings[num_channels]
        if 0 <= channel_idx < len(channels):
            return channels[channel_idx]

    return f"Ch{channel_idx + 1}"