# Video Tutorial 1: Getting Started with Oshun AI Integrations

**Duration:** 15-20 minutes
**Format:** Screen recording with voiceover
**Target Audience:** Developers new to Oshun AI integrations

---

## Video Script

### Opening (0:00 - 0:30)

**[Screen: Oshun logo and title card]**

> Welcome to the Oshun AI Integrations tutorial series. I'm [name], and in this
> video, we'll learn how to set up and use the Oshun AI providers to synthesize
> speech, generate images, and discover models.

**[Screen: Overview slide showing what we'll cover]**

> By the end of this tutorial, you'll be able to:
> - Initialize AI providers
> - Generate speech from text
> - Create AI-generated images
> - Search for models on Civitai

---

### Part 1: Setup (0:30 - 2:30)

**[Screen: Terminal]**

> Let's start by setting up our development environment. First, make sure you
> have Node.js 18 or later installed.

```bash
node --version
# v20.x.x
```

> Next, we'll set up our API keys. You'll need keys from ElevenLabs, RunComfy,
> and optionally Civitai.

**[Screen: Show environment variables]**

```bash
export ELEVENLABS_API_KEY=your_key_here
export RUNCOMFY_API_KEY=your_key_here
export CIVITAI_API_KEY=your_key_here
```

> I recommend storing these in a `.env` file for convenience. Just make sure
> not to commit it to version control.

**[Screen: Create new TypeScript file]**

> Let's create a new file called `ai-demo.ts`. First, we'll import the
> providers we need.

```typescript
import {
  ElevenLabsProvider,
  RunComfyProvider,
  CivitaiProvider,
} from '@oshun/ai-providers';
```

---

### Part 2: Text-to-Speech (2:30 - 6:00)

**[Screen: Code editor]**

> Let's start with text-to-speech using ElevenLabs. First, we create a provider
> instance.

```typescript
const elevenlabs = new ElevenLabsProvider({
  apiKey: process.env.ELEVENLABS_API_KEY!,
});
```

> The exclamation mark tells TypeScript we know this value exists. In
> production, you'd want to add proper validation.

**[Screen: Add synthesis code]**

> Now let's synthesize some text. We call the `synthesize` method with our text
> and a voice ID.

```typescript
const audio = await elevenlabs.synthesize({
  text: 'Hello! Welcome to the Oshun AI tutorial.',
  voiceId: 'EXAVITQu4vr4xnSDxMaL', // Sarah voice
});

console.log(`Generated ${audio.length} bytes of audio`);
```

**[Screen: Run the code]**

> Let's run this and see what happens.

```bash
npx ts-node ai-demo.ts
# Generated 45632 bytes of audio
```

> Excellent! We got audio data back. Let's save it to a file so we can hear it.

```typescript
import { writeFileSync } from 'fs';
writeFileSync('hello.mp3', audio);
```

**[Screen: Play the audio file]**

> And there we have it - our first AI-generated speech!

**[Screen: Show voice settings]**

> You can customize the voice by adjusting settings like stability and
> similarity boost.

```typescript
const audio = await elevenlabs.synthesize({
  text: 'This is a customized voice.',
  voiceId: 'EXAVITQu4vr4xnSDxMaL',
  voiceSettings: {
    stability: 0.3,        // More expressive
    similarity_boost: 0.9, // Close to original
  },
});
```

> Lower stability makes the voice more expressive but less predictable.
> Higher similarity boost keeps it closer to the original voice sample.

---

### Part 3: Image Generation (6:00 - 10:00)

**[Screen: New code section]**

> Now let's generate some images using ComfyUI through RunComfy. We start by
> creating a provider.

```typescript
const runcomfy = new RunComfyProvider({
  apiKey: process.env.RUNCOMFY_API_KEY!,
  maxConcurrentJobs: 5,
});
```

> The `maxConcurrentJobs` setting limits how many images we generate at once.

**[Screen: Submit workflow]**

> To generate an image, we submit a workflow with our prompt.

```typescript
const job = await runcomfy.executeWorkflow({
  workflowId: 'txt2img-sdxl-v1',
  inputs: {
    prompt: 'A majestic dragon flying over mountains at sunset, highly detailed',
    negative_prompt: 'blurry, low quality, watermark',
    width: 1024,
    height: 1024,
    steps: 25,
  },
});

console.log(`Job ID: ${job.id}`);
console.log(`Status: ${job.status}`);
```

**[Screen: Run and show output]**

```bash
npx ts-node ai-demo.ts
# Job ID: job_abc123
# Status: queued
```

> The job is now queued. Image generation takes time, so we need to wait for it.

```typescript
const completed = await runcomfy.waitForCompletion(job.id, {
  timeoutMs: 300000, // 5 minutes
  onStatusChange: (status) => {
    console.log(`Status: ${status}`);
  },
});

if (completed.status === 'completed') {
  console.log('Image generated!');
  console.log(`URL: ${completed.outputs[0].url}`);
}
```

**[Screen: Show generated image]**

> And here's our generated dragon! The AI has created a stunning image based
> on our text description.

---

### Part 4: Model Discovery (10:00 - 13:00)

**[Screen: New code section]**

> Finally, let's explore Civitai to discover AI models. This is optional but
> very useful for finding new models.

```typescript
const civitai = new CivitaiProvider({
  apiKey: process.env.CIVITAI_API_KEY, // Optional
  enableCache: true,
});
```

**[Screen: Search models]**

> We can search for models with various filters.

```typescript
const results = await civitai.searchModels({
  query: 'anime',
  types: ['LORA'],
  baseModels: ['SDXL 1.0'],
  sort: 'Highest Rated',
  limit: 5,
});

for (const model of results.items) {
  console.log(`${model.name} - ${model.stats.downloadCount} downloads`);
}
```

**[Screen: Run and show output]**

```bash
npx ts-node ai-demo.ts
# Anime SDXL v2 - 125,432 downloads
# Character Style Pro - 98,234 downloads
# ...
```

> These are the top-rated anime LoRA models for SDXL. You can use these with
> your image generation to add specific styles.

**[Screen: Get model details]**

> Let's get more details about a specific model.

```typescript
const model = await civitai.getModel(12345);
console.log(`Name: ${model.name}`);
console.log(`Creator: ${model.creator.username}`);
console.log(`Tags: ${model.tags.join(', ')}`);
```

---

### Part 5: Error Handling (13:00 - 15:00)

**[Screen: Error handling code]**

> In production, you'll want to handle errors gracefully. Let's wrap our code
> in try-catch blocks.

```typescript
try {
  const audio = await elevenlabs.synthesize({
    text: 'Test',
    voiceId: 'invalid-voice',
  });
} catch (error) {
  if (error instanceof Error) {
    console.error(`Error: ${error.message}`);

    const apiError = error as any;
    if (apiError.code === 'VOICE_NOT_FOUND') {
      console.log('That voice does not exist. Try listing available voices.');
    }
  }
}
```

**[Screen: Health check]**

> You can also check if providers are healthy before making requests.

```typescript
const healthy = await elevenlabs.healthCheck();
console.log(`ElevenLabs healthy: ${healthy}`);
```

---

### Closing (15:00 - 16:00)

**[Screen: Summary slide]**

> That's it for this introduction! We've learned how to:
> - Set up AI providers with proper configuration
> - Generate speech from text using ElevenLabs
> - Create images using ComfyUI workflows
> - Discover models on Civitai
> - Handle errors gracefully

**[Screen: Resources slide]**

> For more advanced topics, check out:
> - The code examples in the training folder
> - The hands-on exercises
> - The next video on production patterns

> Thanks for watching! If this was helpful, please like and subscribe, and
> I'll see you in the next video.

**[Screen: End card with links]**

---

## B-Roll Suggestions

- Terminal commands being typed
- Code highlighting as it's explained
- Generated audio waveform
- Generated images appearing
- Civitai model browsing
- Error messages being caught

## Notes for Recording

1. Use a clear, moderate speaking pace
2. Pause briefly when switching between code sections
3. Highlight important code with cursor movements
4. Show actual output, not just expected output
5. Keep energy consistent throughout
