> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encord.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Audio

Audio files support annotation using audio region object labels and classifications. Audio regions can be applied to a range (duration in milliseconds) on the audio file. Classifications can only be applied to the entire audio file. Using the Encord SDK you can import audio region labels and classifications directly to audio files that already exist in an Annotate Project. You can also use the SDK to view labels and classifications that exist on an audio file.

## Critical Information

Using classifications on an audio file is similar to using labels or classifications on a video file. There are some critical differences though:

* 1 "frame" = 1 millisecond for audio files when importing classifications.

* When creating a classification for an audio file, the `classification_instance` uses the `range_only=True` argument.

For example, `Classification.create_instance(range_only=True)` or `classification_instance = ClassificationInstance(range_only=True)`

```python theme={"dark"}

ranges = []
for range in classification_instance.get_ranges():
   ranges.append([range.start, range.end])

```

## Audio Regions on Audio Files

### Export Audio Regions on Audio Files

<CodeGroup>
  ```python Template theme={"dark"}

  # Import dependencies
  from pathlib import Path
  from encord import EncordUserClient, Project
  import json

  SSH_PATH = "<file-path-to-your-ssh-key>"
  PROJECT_HASH = "<project-unique-id>"

  # Create user client using access key
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      Path(SSH_PATH).read_text()
  )

  # Get project for which predictions are to be added
  project: Project = user_client.get_project(PROJECT_HASH)

  # Get label rows for your Project
  label_rows = project.list_label_rows_v2()

  # Initialize label rows using bundles
  with project.create_bundle() as bundle:
      for label_row in label_rows:
          label_row.initialise_labels(bundle=bundle)

  # Output directory for JSON files
  output_dir = Path("./label_exports")
  output_dir.mkdir(exist_ok=True)

  # Export each label row to a JSON file
  for label_row in label_rows:
      # Convert label row to dictionary
      label_data = label_row.to_encord_dict()

      # Save the label data to a JSON file
      file_name = f"{label_row.data_title}.json"
      output_path = output_dir / file_name

      with open(output_path, "w", encoding="utf-8") as json_file:
          json.dump(label_data, json_file, indent=4)

      print(f"Exported {label_row.data_title} to {output_path}")

  print("All labels have been exported!")

  ```

  ```python Example theme={"dark"}

  # Import dependencies
  from pathlib import Path
  from encord import EncordUserClient, Project
  import json

  SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
  PROJECT_HASH = "55ee05af-1762-478c-9b3c-d43b4ad39ad4"

  # Create user client using access key
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      Path(SSH_PATH).read_text()
  )

  # Get project for which predictions are to be added
  project: Project = user_client.get_project(PROJECT_HASH)

  # Get label rows for your Project
  label_rows = project.list_label_rows_v2()

  # Initialize label rows using bundles
  with project.create_bundle() as bundle:
      for label_row in label_rows:
          label_row.initialise_labels(bundle=bundle)

  # Output directory for JSON files
  output_dir = Path("./label_exports")
  output_dir.mkdir(exist_ok=True)

  # Export each label row to a JSON file
  for label_row in label_rows:
      # Convert label row to dictionary
      label_data = label_row.to_encord_dict()

      # Save the label data to a JSON file
      file_name = f"{label_row.data_title}.json"
      output_path = output_dir / file_name

      with open(output_path, "w", encoding="utf-8") as json_file:
          json.dump(label_data, json_file, indent=4)

      print(f"Exported {label_row.data_title} to {output_path}")

  print("All labels have been exported!")

  ```
</CodeGroup>

### Import Audio Regions to Audio Files

<CodeGroup>
  ```python Template theme={"dark"}

  # Import dependencies
  from pathlib import Path

  from encord import EncordUserClient, Project
  from encord.objects import (
      Object,
      ObjectInstance,
  )
  from encord.objects.coordinates import AudioCoordinates
  from encord.objects.frames import Range

  SSH_PATH = "<fie-path-to-your-ssh-key>"
  PROJECT_HASH = "<project-unique-id>"

  # Create user client using SSH private key
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      Path(SSH_PATH).read_text()
  )

  # Get the project for which predictions are to be added
  project: Project = user_client.get_project(PROJECT_HASH)

  # Example mapping of data unit titles to start and end frame ranges

  audio_ranges = {
      "<audio-file-01>": [(<start-range-value>, <end-range-value>), (<start-range-value>, <end-range-value>), (<start-range-value>, <end-range-value>)],
      "<audio-file-02>": [(<start-range-value>, <end-range-value>), (<start-range-value>, <end-range-value>)],
      "<audio-file-03>": [(<start-range-value>, <end-range-value>)],
  }

  # Find the ontology object for your Audio Region
  audio_ontology_object: Object = project.ontology_structure.get_child_by_title(
      title="<audio-region-name>", type_=Object
  )

  if audio_ontology_object is None:
      raise ValueError("Audio Region ontology object not found.")

  label_rows = project.list_label_rows_v2()

  # Filter label rows not in range
  def filter_label_rows(label_row) -> bool:
      is_valid = label_row.data_title in audio_ranges
      if not is_valid:
          print(f"Skipping label row: {label_row_title} (no predefined ranges)")
      return is_valid

  label_rows = list(filter(filter_label_rows, label_rows))

  # Initialize label rows using bundles
  with project.create_bundle() as bundle:
      for label_row in label_rows:
          label_row.initialise_labels(bundle=bundle)

  # Loop through each label row and apply updates
  for label_row in label_rows:
      label_row_title = label_row.data_title

      # Apply all ranges as separate objects
      for start, end in audio_ranges.get(label_row_title, []):

          # Instantiate an object instance from the ontology node
          audio_object_instance: ObjectInstance = audio_ontology_object.create_instance()

          # Set object instance with specific start and end frames
          audio_object_instance.set_for_frames(

              coordinates=AudioCoordinates(range=[Range(start=start, end=end)]),  # Adjust as needed
              frames=0,

              manual_annotation=True,
              confidence=1.0,
          )

          # Link the object instance to the label row
          label_row.add_object_instance(audio_object_instance)

          print(f"Added range ({start}, {end}) to label row: {label_row_title}")

      # Upload the label to the server after adding all instances
      label_row.save()
      print(f"Saved label row: {label_row_title}")

  print("Updates applied with predefined frame ranges for each data unit!")

  ```

  ```python Example theme={"dark"}

  # Import dependencies
  from pathlib import Path

  from encord import EncordUserClient, Project
  from encord.objects import (
      Object,
      ObjectInstance,
  )
  from encord.objects.coordinates import AudioCoordinates
  from encord.objects.frames import Range

  SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
  PROJECT_HASH = "55ee05af-1762-478c-9b3c-d43b4ad39ad4"

  # Create user client using SSH private key
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
      Path(SSH_PATH).read_text()
  )

  # Get the project for which predictions are to be added
  project: Project = user_client.get_project(PROJECT_HASH)

  # Example mapping of data unit titles to start and end frame ranges

  audio_ranges = {
      "my-audio-file.mp3": [(8000, 15000), (20000, 25000), (31000, 43003)],
      "your-audio-file.mp3": [(2500, 4500), (6543, 9876)],
      "their-audio-file.mp3": [(4321, 10987)],
  }

  # Find the ontology object for the Audio Region "Speaking"
  audio_ontology_object: Object = project.ontology_structure.get_child_by_title(
      title="Speaking", type_=Object
  )

  if audio_ontology_object is None:
      raise ValueError("Audio Region ontology object not found.")

  label_rows = project.list_label_rows_v2()

  # Filter label rows not in range
  def filter_label_rows(label_row) -> bool:
      is_valid = label_row.data_title in audio_ranges
      if not is_valid:
          print(f"Skipping label row: {label_row_title} (no predefined ranges)")
      return is_valid

  label_rows = list(filter(filter_label_rows, label_rows))

  # Initialize label rows using bundles
  with project.create_bundle() as bundle:
      for label_row in label_rows:
          label_row.initialise_labels(bundle=bundle)

  # Loop through each label row and apply updates
  for label_row in label_rows:
      label_row_title = label_row.data_title
      
      # Apply all ranges as separate objects
      for start, end in audio_ranges.get(label_row_title, []):

          # Instantiate an object instance from the ontology node
          audio_object_instance: ObjectInstance = audio_ontology_object.create_instance()

          # Set object instance with specific start and end frames
          audio_object_instance.set_for_frames(
              coordinates=AudioCoordinates(range=[Range(start=start, end=end)]),  # Adjust as needed
              frames=0,
              manual_annotation=True,
              confidence=1.0,
          )

          # Link the object instance to the label row
          label_row.add_object_instance(audio_object_instance)

          print(f"Added range ({start}, {end}) to label row: {label_row_title}")

      # Upload the label to the server after adding all instances
      label_row.save()
      print(f"Saved label row: {label_row_title}")

  print("Updates applied with predefined frame ranges for each data unit!")

  ```
</CodeGroup>

## Classifications on Audio Files

### View Classifications on Audio Files

```python theme={"dark"}

# Import dependencies
from encord import EncordUserClient

# Instantiate client
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Specify Project
project = user_client.get_project("<project_id>")

# Downloads a local copy of all the labels
label_rows = project.list_label_rows_v2(include_all_label_branches=True) 

# Initialize label rows using bundles
with project.create_bundle() as bundle:
    for label_row in label_rows:
        label_row.initialise_labels(bundle=bundle)

for label_row in label_rows:
    print(f"Title: {label_row.data_title}, branch: {label_row.branch_name}")

    # Print all essential classification information
    for classification_instance in label_row.get_classification_instances():
        print(f"classificationHash: {classification_instance.classification_hash}")
        print(f"Classification name: {classification_instance.classification_name}")
        print(f"featureHash: {classification_instance.feature_hash}")
        print(f"Classification answer: {classification_instance.get_answer().value}")
        print(f"Classification answer hash: {classification_instance.get_answer().feature_node_hash}")

```

### Export Classifications from Audio Files

```python Template theme={"dark"}

# Import dependencies
from encord import EncordUserClient
import json

SSH_PATH = "<path-to-your-ssh-private-key>"

PROJECT_ID = "<your-project-id>"

# Authenticate with Encord using the path to your private key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path=SSH_PATH
)

# Specify Project
project = user_client.get_project(PROJECT_ID)

# Downloads a local copy of all the labels
label_rows = project.list_label_rows_v2(include_all_label_branches=True) 

# Initialize label rows using bundles
with project.create_bundle() as bundle:
    for label_row in label_rows:
        label_row.initialise_labels(bundle=bundle)

for label_row in label_rows:
    print(f"Title: {label_row.data_title}, branch: {label_row.branch_name}")

    # Export classifications
    classifications = []
    for classification_instance in label_row.get_classification_instances():
        classification_data = {
            "classificationHash": classification_instance.classification_hash,
            "name": classification_instance.classification_name,
            "featureHash": classification_instance.feature_hash,
            "answer": classification_instance.get_answer().value,
            "answerHash": classification_instance.get_answer().feature_node_hash,
        }
        classifications.append(classification_data)
    
    # Print or save the exported classifications
    print(json.dumps(classifications, indent=2))
    # Alternatively, you can save to a file:
    # with open(f"{label_row.data_title}_classifications.json", "w") as f:
    #     json.dump(classifications, f, indent=2)

```

### Import Classifications to Audio Files

<CodeGroup>
  ```python Template theme={"dark"}

  # Import dependencies
  from pathlib import Path
  from encord import EncordUserClient, Project
  from encord.objects import Classification
  from encord.objects.options import Option

  SSH_PATH = "<file-path-to-your-ssh-key>"
  PROJECT_ID = "<project-unique-id>"

  # Instantiate Encord client
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH
  )

  # Specify the project
  project = user_client.get_project(PROJECT_ID)

  # Define a mapping where each file has a list of classifications and options
  file_classification_mapping = {
      "<audio-file-01.file-extension>": [
          {"classification_name": "<classification-name-01>", "option_title": "<option-value>"},
          {"classification_name": "<classification-name-02>", "option_title": "<option-value>"},
      ],
      "<audio-file-02.file-extension>": [
          {"classification_name": "<classification-name-01>", "option_title": "<option-value>"},
      ],
      "<audio-file-03.file-extension>": [
          {"classification_name": "<classification-name-01>", "option_title": "<option-value>"},
      ],
      # Add more mappings as needed
  }

  # Loop through the mapping to apply classifications to each unique file
  for file_name, classifications in file_classification_mapping.items():
      try:
          # Fetch the label row for the given file name
          label_row = project.list_label_rows_v2(data_title_eq=file_name)[0]

          print(label_row.data_hash)

          label_row.initialise_labels()

          for classification_data in classifications:
              # Fetch the classification from the ontology
              ontology_classification: Classification = project.ontology_structure.get_child_by_title(
                  title=classification_data["classification_name"],
                  type_=Classification,
              )

              # Fetch the classification option
              option = ontology_classification.get_child_by_title(
                  title=classification_data["option_title"], type_=Option
              )

              # Create a classification instance
              # range_only=True must be used when creating the classification
              classification_instance = ontology_classification.create_instance(range_only=True)
              classification_instance.set_answer(answer=option)

              # Set classification to apply to frame 0
              classification_instance.set_for_frames(
                  frames=0,
                  manual_annotation=True,
                  confidence=1.0,
              )

              # Add classification instance to the label row
              label_row.add_classification_instance(classification_instance)

          # Save the updated label row after all classifications are added
          label_row.save()

          print(f"Successfully updated classifications for {file_name}.")
      except Exception as e:
          print(f"Failed to update classifications for {file_name}: {e}")

  ```

  ```python Example theme={"dark"}

  # Import dependencies
  from pathlib import Path
  from encord import EncordUserClient, Project
  from encord.objects import Classification
  from encord.objects.options import Option

  SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
  PROJECT_ID = "f60f33cd-213b-400a-b974-7a6a6687a24c"

  # Instantiate Encord client
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path=SSH_PATH
  )

  # Specify the project
  project = user_client.get_project(PROJECT_ID)

  # Define a mapping where each file has a list of classifications and options
  file_classification_mapping = {
      "sh-b-p.mp3": [
          {"classification_name": "Person speaking", "option_title": "Yes"},
          {"classification_name": "Volume", "option_title": "Loud"},
      ],
      "superhero-trailer-110450.mp3": [
          {"classification_name": "Person speaking", "option_title": "No"},
      ],
      "stomping-rock-four-shots-111444.mp3": [
          {"classification_name": "Person speaking", "option_title": "No"},
      ],
      # Add more mappings as needed
  }

  # Loop through the mapping to apply classifications to each unique file
  for file_name, classifications in file_classification_mapping.items():
      try:
          # Fetch the label row for the given file name
          label_row = project.list_label_rows_v2(data_title_eq=file_name)[0]

          print(label_row.data_hash)

          label_row.initialise_labels()

          for classification_data in classifications:
              # Fetch the classification from the ontology
              ontology_classification: Classification = project.ontology_structure.get_child_by_title(
                  title=classification_data["classification_name"],
                  type_=Classification,
              )

              # Fetch the classification option
              option = ontology_classification.get_child_by_title(
                  title=classification_data["option_title"], type_=Option
              )

              # Create a classification instance
              # range_only=True must be used when creating the classification
              classification_instance = ontology_classification.create_instance(range_only=True)
              classification_instance.set_answer(answer=option)

              # Set classification to apply to frame 0
              classification_instance.set_for_frames(
                  frames=0,
                  manual_annotation=True,
                  confidence=1.0,
              )

              # Add classification instance to the label row
              label_row.add_classification_instance(classification_instance)

          # Save the updated label row after all classifications are added
          label_row.save()

          print(f"Successfully updated classifications for {file_name}.")
      except Exception as e:
          print(f"Failed to update classifications for {file_name}: {e}")


  ```
</CodeGroup>
