Files
TuneRipper/TuneRipper/API_USAGE_EXAMPLES.md
T
Michal Vrba 160b7e7115 Streamline video conversion workflow & UI integration
Removed /api/video/details endpoint; video details now fetched as first step of processing and included in progress/status responses. Updated backend models and controller logic to support integrated workflow and improved error handling. Refactored frontend to show video info and conversion progress in real time, removed legacy API calls, and enhanced UI/UX with responsive video info cards and progress bars. Updated documentation and example code to reflect new workflow.
2025-12-11 14:59:14 +01:00

9.6 KiB

TuneRipper API Service Usage Examples

Injecting the Service

In any Razor component, inject the API service:

@inject ITuneRipperApiService ApiService

Updated API Workflow

The API has been streamlined - video details are now fetched as the first step of processing, eliminating the need for a separate details endpoint.

New Workflow:

  1. Start Processing - Includes video details fetching as first step
  2. Monitor Status - Video details appear when progress reaches ~15%
  3. Get Final Result - Complete processing result with download URL

Usage Examples

1. Start Video Processing (includes video details fetching)

private async Task StartProcessingExample()
{
    var request = new ProcessVideoRequest
    {
        Url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        Format = "mp3",
        Quality = "128"
    };
    
    var response = await ApiService.StartProcessingAsync(request);
    
    if (response?.Success == true)
    {
        var jobId = response.FileName; // This contains the job ID
        await MonitorProcessingWithVideoDetails(jobId);
    }
}

2. Monitor Processing Status (includes video details when available)

private async Task MonitorProcessingWithVideoDetails(string jobId)
{
    YouTubeVideoDetails? videoDetails = null;
    bool detailsReceived = false;
    
    while (true)
    {
        var status = await ApiService.GetProcessingStatusAsync(jobId);
        
        if (status == null) break;
        
        Console.WriteLine($"Progress: {status.PercentageComplete}% - {status.Message}");
        
        // Video details become available at ~15% progress
        if (!detailsReceived && status.VideoDetails != null)
        {
            videoDetails = status.VideoDetails;
            detailsReceived = true;
            
            Console.WriteLine($"Video Details Received:");
            Console.WriteLine($"  Title: {videoDetails.Title}");
            Console.WriteLine($"  Author: {videoDetails.Author}");
            Console.WriteLine($"  Duration: {videoDetails.Duration}");
        }
        
        if (status.Status == "Completed" || status.Status == "Failed")
        {
            break;
        }
        
        await Task.Delay(2000); // Poll every 2 seconds
    }
    
    // Get final result
    var result = await ApiService.GetProcessingResultAsync(jobId);
    if (result?.Success == true)
    {
        Console.WriteLine($"Processing completed! Download: {result.DownloadUrl}");
    }
}

3. Complete Processing Workflow

private async Task CompleteWorkflowExample()
{
    try
    {
        // Step 1: Start processing
        var request = new ProcessVideoRequest
        {
            Url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
            Format = "mp3",
            Quality = "128"
        };
        
        var startResponse = await ApiService.StartProcessingAsync(request);
        if (startResponse?.Success != true)
        {
            Console.WriteLine($"Failed to start processing: {startResponse?.Message}");
            return;
        }
        
        var jobId = startResponse.FileName;
        Console.WriteLine($"Processing started with job ID: {jobId}");
        
        // Step 2: Monitor progress and get video details
        YouTubeVideoDetails? videoDetails = null;
        bool processingComplete = false;
        
        while (!processingComplete)
        {
            var status = await ApiService.GetProcessingStatusAsync(jobId);
            
            if (status == null)
            {
                Console.WriteLine("Failed to get status");
                break;
            }
            
            Console.WriteLine($"{status.PercentageComplete}%: {status.Message}");
            
            // Capture video details when they become available
            if (videoDetails == null && status.VideoDetails != null)
            {
                videoDetails = status.VideoDetails;
                Console.WriteLine($"?? Video: {videoDetails.Title} by {videoDetails.Author}");
            }
            
            if (status.Status == "Completed")
            {
                processingComplete = true;
            }
            else if (status.Status == "Failed")
            {
                Console.WriteLine($"Processing failed: {status.Message}");
                return;
            }
            
            if (!processingComplete)
            {
                await Task.Delay(2000);
            }
        }
        
        // Step 3: Get final result
        var result = await ApiService.GetProcessingResultAsync(jobId);
        if (result?.Success == true)
        {
            Console.WriteLine($"? Success! File: {result.FileName}");
            Console.WriteLine($"?? Download: {result.DownloadUrl}");
            
            // Step 4: Download the file
            var fileBytes = await ApiService.DownloadFileAsync(jobId);
            if (fileBytes != null)
            {
                Console.WriteLine($"?? Downloaded {fileBytes.Length} bytes");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

4. Download File

private async Task DownloadFileExample(string jobId)
{
    var fileBytes = await ApiService.DownloadFileAsync(jobId);
    
    if (fileBytes != null)
    {
        // In a Blazor component, you might trigger a download
        // This would require additional JavaScript interop
        Console.WriteLine($"Downloaded {fileBytes.Length} bytes");
    }
}

5. Check API Health

private async Task CheckApiHealthExample()
{
    var isHealthy = await ApiService.IsApiHealthyAsync();
    
    if (isHealthy)
    {
        Console.WriteLine("API is healthy and responding");
    }
    else
    {
        Console.WriteLine("API is not responding or unhealthy");
    }
}

6. Error Handling

private async Task ErrorHandlingExample()
{
    try
    {
        var request = new ProcessVideoRequest
        {
            Url = "invalid-url",
            Format = "mp3",
            Quality = "128"
        };
        
        var response = await ApiService.StartProcessingAsync(request);
        
        if (response?.Success != true)
        {
            Console.WriteLine($"Processing failed: {response?.Message}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
    }
}

Configuration

The API service automatically uses the configuration from appsettings.json:

{
  "ApiSettings": {
    "BaseUrl": "https://localhost:7160",
    "HttpBaseUrl": "http://localhost:5112",
    "TimeoutSeconds": 30,
    "EnableLogging": true,
    "RetryAttempts": 3,
    "RetryDelaySeconds": 2
  }
}

API Endpoints

Current Endpoints:

  • POST /api/video/process - Start processing (includes video details fetching)
  • GET /api/video/status/{jobId} - Get processing status (includes video details when available)
  • GET /api/video/result/{jobId} - Get final processing result
  • GET /api/video/jobs - List all processing jobs
  • GET /api/download/{jobId} - Download converted file
  • GET /api/health - Health check

Removed Endpoints:

  • GET /api/video/details?url={url} - Removed (now integrated into processing)

Complete Component Example

@page "/example"
@inject ITuneRipperApiService ApiService

<h3>Integrated Video Processing</h3>

<input @bind="youtubeUrl" placeholder="YouTube URL" />
<button @onclick="StartProcessing" disabled="@isProcessing">
    @(isProcessing ? "Processing..." : "Convert Video")
</button>

@if (currentVideo != null)
{
    <div class="video-info">
        <h4>@currentVideo.Title</h4>
        <p>By: @currentVideo.Author</p>
        <p>Duration: @currentVideo.Duration</p>
    </div>
}

@if (isProcessing)
{
    <div class="progress">
        <div class="progress-bar" style="width: @(progressPercent)%"></div>
        <span>@progressMessage (@progressPercent%)</span>
    </div>
}

@code {
    private string youtubeUrl = "";
    private bool isProcessing = false;
    private int progressPercent = 0;
    private string progressMessage = "";
    private YouTubeVideoDetails? currentVideo = null;

    private async Task StartProcessing()
    {
        if (string.IsNullOrWhiteSpace(youtubeUrl)) return;
        
        isProcessing = true;
        currentVideo = null;
        progressPercent = 0;
        
        try
        {
            // Start processing
            var request = new ProcessVideoRequest { Url = youtubeUrl, Format = "mp3", Quality = "128" };
            var response = await ApiService.StartProcessingAsync(request);
            
            if (response?.Success == true)
            {
                await MonitorProgress(response.FileName);
            }
        }
        finally
        {
            isProcessing = false;
        }
    }
    
    private async Task MonitorProgress(string jobId)
    {
        while (isProcessing)
        {
            var status = await ApiService.GetProcessingStatusAsync(jobId);
            
            if (status != null)
            {
                progressPercent = status.PercentageComplete;
                progressMessage = status.Message ?? "Processing...";
                
                // Video details appear at ~15%
                if (currentVideo == null && status.VideoDetails != null)
                {
                    currentVideo = status.VideoDetails;
                }
                
                if (status.Status == "Completed" || status.Status == "Failed")
                {
                    break;
                }
            }
            
            StateHasChanged();
            await Task.Delay(2000);
        }
    }
}