# Action Table - Audio

## **1. Introduction**

This tutorial will guide you through using the JamAI Base SDK to create a simple audio information processing system.

**What We'll Build**

Automate tasks with audio! Imagine processing meeting recordings or voice memos automatically.

In this tutorial, we'll create an audio processing system that:

* Takes an audio file as input (e.g., `.mp3`, `.wav`).
* Uploads it to a JamAI Base action table.
* Extracts and generates key information such as:
  * Transcription of the audio content.
  * Summary of the audio.

**Prerequisites**

Before starting, you'll need:

* Python 3.11 or higher installed
* Project ID and Personal Access Token (PAT)

## **2. Installation and Setup**

**Installing the SDK**

```bash
pip install jamaibase
```

**Basic Configuration**

Get your Personal Access Token (PAT) here:

<figure><img src="/files/TUeYMAA4tQsG2PRltaFZ" alt=""><figcaption><p>How to generate PAT</p></figcaption></figure>

Get your Project ID here:

<figure><img src="/files/pz1Gr6LRLftmj8PXqcX0" alt=""><figcaption><p>How to get Project ID</p></figcaption></figure>

```python
from jamaibase import JamAI, types as t 

PROJECT_ID = "your_project_id"
PAT = "your_PAT"

client = JamAI(
    project_id=PROJECT_ID,
    token=PAT
)
```

## **3. Creating Your Action Table**

For simplicity, you can set up your action table in the JamAI Base platform:

1. Navigate to your JamAI Base action table tab.
2. Create a new action table named "AudioProcessor".

<figure><img src="/files/W03S51nU7WGHWXcnahaJ" alt=""><figcaption></figcaption></figure>

3. Configure the following columns:

```
Input Column:
- Name: "Audio"
- Type: Audio

Output Columns:
- Name: "Transcription"
  Type: Text
  ☑️ Output checkbox enabled

- Name: "Summary"
  Type: Text
  ☑️ Output checkbox enabled
```

<figure><img src="/files/M8sL4wwz0YjSVulb97Hb" alt=""><figcaption><p>Create a new action table</p></figcaption></figure>

<figure><img src="/files/1rIiMAik5P7knCxIoYL5" alt=""><figcaption><p>Created action table</p></figcaption></figure>

## **4. Basic Implementation**

### **4.1 Simple Audio Processor**

```python
def process_single_audio(audio_path):
    # Upload audio file
    file_response = client.file.upload_file(audio_path)

    # Process in action table
    response = client.table.add_table_rows(
        table_type=t.TableType.ACTION,
        request=t.RowAddRequest(
            table_id="AudioProcessor",
            data=[{"Audio": file_response.uri}],
            stream=False,
        ),
    )

    # Extract results
    return {
        "transcription": response.rows[0].columns["Transcription"].text,
        "summary": response.rows[0].columns["Summary"].text
    }
```

### **4.2 Complete Implementation with Error Handling**

```python
import os
from typing import Dict, Optional

class AudioProcessor:
    def __init__(self, project_id: str, pat: str):
        self.client = JamAI(
            project_id=project_id,
            token=pat
        )

    def validate_audio(self, audio_path: str) -> bool:
        """Validate if file exists and has correct extension"""
        if not os.path.exists(audio_path):
            raise FileNotFoundError(f"Audio file not found: {audio_path}")

        valid_extensions = ['.mp3', '.wav']
        file_ext = os.path.splitext(audio_path)[1].lower()
        if file_ext not in valid_extensions:
            raise ValueError(f"Unsupported file format. Use: {valid_extensions}")

        return True

    def process_audio(self, audio_path: str) -> Optional[Dict[str, str]]:
        """Process a single audio file"""
        try:
            # Validate audio
            self.validate_audio(audio_path)

            # Upload file
            print("Uploading audio...")
            file_response = self.client.file.upload_file(audio_path)
            print(f"Upload successful: {file_response.uri}")

            # Process in action table
            print("Processing audio...")
            response = self.client.table.add_table_rows(
                table_type=t.TableType.ACTION,
                request=t.RowAddRequest(
                    table_id="AudioProcessor",
                    data=[{"Audio": file_response.uri}],
                    stream=False,
                ),
            )

            # Extract and return results
            results = {
                "transcription": response.rows[0].columns["Transcription"].text,
                "summary": response.rows[0].columns["Summary"].text
            }
            print("Processing complete!")
            return results

        except Exception as e:
            print(f"Error processing audio: {str(e)}")
            return None
```

## **5. Usage Examples**

### **5.1 Basic Usage**

```python
# Initialize processor
processor = AudioProcessor(PROJECT_ID, PAT)

# Process single audio
result = processor.process_audio("path/to/audio.mp3")

if result:
    print(f"Transcription: {result['transcription']}")
    print(f"Summary: {result['summary']}")
```

### **5.2 Batch Processing**

```python
def process_audio_batch(audio_folder: str):
    processor = AudioProcessor(PROJECT_ID, PAT)
    results = []

    for filename in os.listdir(audio_folder):
        if filename.lower().endswith(('.mp3', '.wav')):
            audio_path = os.path.join(audio_folder, filename)
            result = processor.process_audio(audio_path)
            if result:
                results.append({
                    "filename": filename,
                    **result
                })

    return results

# Usage
results = process_audio_batch("path/to/audio/folder")
for result in results:
    print(f"File: {result['filename']}")
    print(f"Transcription: {result['transcription']}")
    print(f"Summary: {result['summary']}")
    print("---")
```

## **6. Best Practices**

**Error Handling**

* Always validate input audio files.
* Handle network errors gracefully.
* Consider adding specific error handling for audio processing failures (e.g., silence, corrupted files).

**Performance**

* Reuse the client instance.
* Consider batch processing for multiple files.
* Implement rate limiting for large batches if needed.

**Security**

* Use environment variables for credentials.

**Complete Standalone Example**

Save this as `audio_processor.py`:

```python
import os
import argparse
from jamaibase import JamAI, protocol as p
from typing import Dict, Optional

class AudioProcessor:
    def __init__(self, project_id: str, pat: str):
        self.client = JamAI(
            project_id=project_id,
            token=pat
        )

    def validate_audio(self, audio_path: str) -> bool:
        if not os.path.exists(audio_path):
            raise FileNotFoundError(f"Audio file not found: {audio_path}")

        valid_extensions = ['.mp3', '.wav'] 
        file_ext = os.path.splitext(audio_path)[1].lower()
        if file_ext not in valid_extensions:
            raise ValueError(f"Unsupported file format. Use: {valid_extensions}")

        return True

    def process_audio(self, audio_path: str) -> Optional[Dict[str, str]]:
        try:
            self.validate_audio(audio_path)

            print(f"Processing audio: {audio_path}")
            print("Uploading audio...")
            file_response = self.client.file.upload_file(audio_path)
            print(f"Upload successful!")

            print("Extracting information...")
            response = self.client.table.add_table_rows(
                table_type=t.TableType.ACTION,
                request=t.RowAddRequest(
                    table_id="AudioProcessor",
                    data=[{"Audio": file_response.uri}],
                    stream=False,
                ),
            )

            results = {
                "transcription": response.rows[0].columns["Transcription"].text,
                "summary": response.rows[0].columns["Summary"].text
            }
            return results

        except Exception as e:
            print(f"Error: {str(e)}")
            return None

def process_folder(folder_path: str, processor: AudioProcessor) -> None:
    """Process all audio files in a folder"""
    if not os.path.exists(folder_path):
        print(f"Folder not found: {folder_path}")
        return

    results = []
    for filename in os.listdir(folder_path):
        if filename.lower().endswith(('.mp3', '.wav')):
            audio_path = os.path.join(folder_path, filename)
            result = processor.process_audio(audio_path)
            if result:
                results.append({
                    "filename": filename,
                    **result
                })

    # Print results in a formatted way
    print("\nProcessing Results:")
    print("-" * 50)
    for result in results:
        print(f"File: {result['filename']}")
        print(f"Transcription: {result['transcription']}")
        print(f"Summary: {result['summary']}")
        print("-" * 50)

def main():
    # Set up argument parser
    parser = argparse.ArgumentParser(description='Process audio files using JamAIBase')
    parser.add_argument('--project-id', required=True, help='Your JamAIBase project ID')
    parser.add_argument('--pat', required=True, help='Your Personal Access Token')
    parser.add_argument('--input', required=True, help='Path to audio file or folder')

    args = parser.parse_args()

    # Initialize processor
    processor = AudioProcessor(args.project_id, args.pat)

    # Process input
    if os.path.isfile(args.input):
        # Single file processing
        result = processor.process_audio(args.input)
        if result:
            print("\nResults:")
            print("-" * 50)
            print(f"Transcription: {result['transcription']}")
            print(f"Summary: {result['summary']}")
            print("-" * 50)
    else:
        # Folder processing
        process_folder(args.input, processor)

if __name__ == "__main__":
    main()
```

**How to Run**

1. Save the code above as `audio_processor.py`
2. Install required package:

   ```bash
   pip install jamaibase
   ```
3. Run for a single audio file:

   ```bash
   python audio_processor.py --project-id "your_project_id" --pat "your_pat" --input "path/to/audio.mp3"
   ```
4. Run for a folder of audio files:

   ```bash
   python audio_processor.py --project-id "your_project_id" --pat "your_pat" --input "path/to/audio/folder"
   ```

**Example Output**

```
Processing audio: discussion_recording.mp3
Uploading audio...
Upload successful!
Extracting information...

Results:
--------------------------------------------------
Transcription: ... [The full transcription of the audio] ...
Summary: This audio discusses the cost of AI model training. Stanford researchers...
--------------------------------------------------
```

<figure><img src="/files/CUMmoYPGFqwkYl6D5HZw" alt=""><figcaption><p>The AudioProcessor table with the uploaded audio.</p></figcaption></figure>

**Features**

* Processes single audio files or entire folders.
* Validates audio file types and existence.
* Provides clear progress feedback.
* Formats results (transcription and summary) in an easy-to-read way.
* Includes error handling.
* Command-line argument support.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.jamaibase.com/developer-reference/python-sdk-documentation/quick-start-action-table/action-table-audio.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
