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.
This commit is contained in:
@@ -21,6 +21,7 @@ public class VideoController : ControllerBase
|
||||
public ProcessVideoRequest Request { get; set; } = new();
|
||||
public DownloadProgress Progress { get; set; } = new();
|
||||
public ProcessVideoResponse? Result { get; set; }
|
||||
public YouTubeVideoDetails? VideoDetails { get; set; } // Add video details to job
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
@@ -30,39 +31,6 @@ public class VideoController : ControllerBase
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet("details")]
|
||||
public async Task<ActionResult<YouTubeVideoDetails>> GetVideoDetails([FromQuery] string url)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
return BadRequest("URL is required");
|
||||
}
|
||||
|
||||
if (!_videoService.IsValidYouTubeUrl(url))
|
||||
{
|
||||
return BadRequest("Invalid YouTube URL");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Fetching video details for URL: {Url}", url);
|
||||
|
||||
var videoDetails = await _videoService.GetVideoDetailsAsync(url);
|
||||
|
||||
if (videoDetails == null)
|
||||
{
|
||||
return NotFound("Video not found or unavailable");
|
||||
}
|
||||
|
||||
return Ok(videoDetails);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error fetching video details for URL: {Url}", url);
|
||||
return StatusCode(500, $"Error fetching video details: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("process")]
|
||||
public async Task<ActionResult<ProcessVideoResponse>> StartProcessing([FromBody] ProcessVideoRequest request)
|
||||
{
|
||||
@@ -132,7 +100,22 @@ public class VideoController : ControllerBase
|
||||
return NotFound("Job not found");
|
||||
}
|
||||
|
||||
return Ok(job.Progress);
|
||||
// Return progress with video details if available
|
||||
var progress = job.Progress;
|
||||
|
||||
// If we have video details and we're past the first step, include them in a custom response
|
||||
if (job.VideoDetails != null && job.Progress.PercentageComplete >= 15)
|
||||
{
|
||||
return Ok(new
|
||||
{
|
||||
PercentageComplete = progress.PercentageComplete,
|
||||
Status = progress.Status,
|
||||
Message = progress.Message,
|
||||
VideoDetails = job.VideoDetails
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(progress);
|
||||
}
|
||||
|
||||
[HttpGet("result/{jobId}")]
|
||||
@@ -182,19 +165,38 @@ public class VideoController : ControllerBase
|
||||
{
|
||||
_logger.LogInformation("Processing video for job {JobId}", jobId);
|
||||
|
||||
// Simulate video processing steps
|
||||
var steps = new[]
|
||||
// Step 1: Fetch video details (NEW FIRST STEP)
|
||||
job.Progress.Status = "Processing";
|
||||
job.Progress.Message = "Fetching video details...";
|
||||
job.Progress.PercentageComplete = 5;
|
||||
|
||||
_logger.LogInformation("Job {JobId}: Fetching video details", jobId);
|
||||
|
||||
var videoDetails = await _videoService.GetVideoDetailsAsync(job.Request.Url!);
|
||||
|
||||
if (videoDetails == null)
|
||||
{
|
||||
("Fetching video information", 10),
|
||||
("Analyzing audio stream", 25),
|
||||
throw new Exception("Unable to fetch video details. Invalid URL or video unavailable.");
|
||||
}
|
||||
|
||||
// Store video details in the job
|
||||
job.VideoDetails = videoDetails;
|
||||
job.Progress.Message = "Video details retrieved successfully";
|
||||
job.Progress.PercentageComplete = 15;
|
||||
|
||||
_logger.LogInformation("Job {JobId}: Video details retrieved - Title: {Title}", jobId, videoDetails.Title);
|
||||
|
||||
// Continue with remaining processing steps
|
||||
var remainingSteps = new[]
|
||||
{
|
||||
("Analyzing audio stream", 30),
|
||||
("Downloading audio data", 60),
|
||||
("Converting to MP3", 85),
|
||||
("Finalizing", 100)
|
||||
};
|
||||
|
||||
foreach (var (message, percentage) in steps)
|
||||
foreach (var (message, percentage) in remainingSteps)
|
||||
{
|
||||
job.Progress.Status = "Processing";
|
||||
job.Progress.Message = message;
|
||||
job.Progress.PercentageComplete = percentage;
|
||||
|
||||
@@ -204,9 +206,6 @@ public class VideoController : ControllerBase
|
||||
await Task.Delay(Random.Shared.Next(1000, 3000));
|
||||
}
|
||||
|
||||
// Get video details using the service
|
||||
var videoDetails = await _videoService.GetVideoDetailsAsync(job.Request.Url!);
|
||||
|
||||
// Complete processing
|
||||
job.Progress.Status = "Completed";
|
||||
job.Progress.Message = "Processing completed successfully";
|
||||
@@ -216,7 +215,7 @@ public class VideoController : ControllerBase
|
||||
{
|
||||
Success = true,
|
||||
Message = "Video processed successfully",
|
||||
FileName = $"{videoDetails?.Title?.Replace(" ", "_") ?? "video"}.{job.Request.Format ?? "mp3"}",
|
||||
FileName = $"{videoDetails.Title?.Replace(" ", "_") ?? "video"}.{job.Request.Format ?? "mp3"}",
|
||||
DownloadUrl = $"/api/download/{jobId}",
|
||||
VideoDetails = videoDetails
|
||||
};
|
||||
@@ -237,7 +236,7 @@ public class VideoController : ControllerBase
|
||||
Message = ex.Message,
|
||||
FileName = null,
|
||||
DownloadUrl = null,
|
||||
VideoDetails = null
|
||||
VideoDetails = job.VideoDetails // Include video details even on failure if we got them
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user