From 1895962f550b46df3284741ea4f949f19d6fc923 Mon Sep 17 00:00:00 2001 From: DenChika Date: Mon, 27 Jun 2022 14:50:05 +0500 Subject: [PATCH 1/2] Feat: implement set bitrate of tracks --- .../Controllers/SetBitrateController.cs | 87 +++++++++++++++++++ Sonar.Player/Sonar.Player.Api/Program.cs | 2 + .../Properties/Bitrate/Commands/SetBitrate.cs | 57 ++++++++++++ .../Properties/Settings.cs | 16 ++++ .../TracksStorage/HlsTrackProcessor.cs | 3 +- .../Tools/BitrateEnum.cs | 8 ++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs create mode 100644 Sonar.Player/Sonar.Player.Application/Properties/Bitrate/Commands/SetBitrate.cs create mode 100644 Sonar.Player/Sonar.Player.Application/Properties/Settings.cs create mode 100644 Sonar.Player/Sonar.Player.Application/Tools/BitrateEnum.cs diff --git a/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs b/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs new file mode 100644 index 0000000..a8c1ded --- /dev/null +++ b/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs @@ -0,0 +1,87 @@ +using MediatR; +using Microsoft.AspNetCore.Mvc; +using Sonar.Player.Api.Controllers.Dto; +using Sonar.Player.Application.Properties.Bitrate.Commands; +using Sonar.Player.Application.Queue.Commands; +using Sonar.Player.Application.Queue.Queries; +using Sonar.Player.Application.Services; +using Sonar.Player.Application.Tools; + +namespace Sonar.Player.Api.Controllers; + +[ApiController] +[Route("[controller]")] +public class SetBitrateController : Controller +{ + private readonly IMediator _mediator; + private readonly IUserService _userService; + + public SetBitrateController(IMediator mediator, IUserService userService) + { + _mediator = mediator; + _userService = userService; + } + + [HttpPatch("lowBitrate")] + public async Task> SetLowAsync( + [FromHeader(Name = "Token")] string token, + [FromQuery(Name = "id")] Guid trackId, + [FromForm] TrackFormDto form, + CancellationToken cancellationToken) + { + await using var fileStream = form.File.OpenReadStream(); + return Ok( + await _mediator.Send( + new SetBitrate.Command( + token, + trackId, + form.Name, + new SetBitrate.Command.TrackFile( + form.File.FileName, + fileStream), + (int) BitrateEnum.LowBitrate + ), cancellationToken)); + } + + [HttpPatch("mediumBitrate")] + public async Task> SetMediumAsync( + [FromHeader(Name = "Token")] string token, + [FromQuery(Name = "id")] Guid trackId, + [FromForm] TrackFormDto form, + CancellationToken cancellationToken) + { + await using var fileStream = form.File.OpenReadStream(); + return Ok( + await _mediator.Send( + new SetBitrate.Command( + token, + trackId, + form.Name, + new SetBitrate.Command.TrackFile( + form.File.FileName, + fileStream), + (int) BitrateEnum.MediumBitrate + ), cancellationToken)); + } + + [HttpPatch("highBitrate")] + public async Task> SetHighAsync( + [FromHeader(Name = "Token")] string token, + [FromQuery(Name = "id")] Guid trackId, + [FromForm] TrackFormDto form, + CancellationToken cancellationToken) + { + await using var fileStream = form.File.OpenReadStream(); + return Ok( + await _mediator.Send( + new SetBitrate.Command( + token, + trackId, + form.Name, + new SetBitrate.Command.TrackFile( + form.File.FileName, + fileStream), + (int) BitrateEnum.HighBitrate + ), cancellationToken)); + } +} \ No newline at end of file diff --git a/Sonar.Player/Sonar.Player.Api/Program.cs b/Sonar.Player/Sonar.Player.Api/Program.cs index ab0e5f8..35396f9 100644 --- a/Sonar.Player/Sonar.Player.Api/Program.cs +++ b/Sonar.Player/Sonar.Player.Api/Program.cs @@ -3,6 +3,7 @@ using Serilog; using Sonar.Player.Api.Bootstraps; using Sonar.Player.Api.Filters; +using Sonar.Player.Application.Properties; using Sonar.Player.Application.Services; using Sonar.Player.Application.Services.TracksStorage; using Sonar.Player.Application.Tools; @@ -13,6 +14,7 @@ var builder = WebApplication.CreateBuilder(args); +var settings = Settings.GetInstance(); builder.Host.UseSerilog((ctx, lc) => lc.WriteTo.Console()); builder.Services.AddControllers(options => options.Filters.Add()); diff --git a/Sonar.Player/Sonar.Player.Application/Properties/Bitrate/Commands/SetBitrate.cs b/Sonar.Player/Sonar.Player.Application/Properties/Bitrate/Commands/SetBitrate.cs new file mode 100644 index 0000000..9ea69a1 --- /dev/null +++ b/Sonar.Player/Sonar.Player.Application/Properties/Bitrate/Commands/SetBitrate.cs @@ -0,0 +1,57 @@ +using System.Linq; +using MediatR; +using Sonar.Player.Application.Services.TracksStorage; +using Sonar.Player.Application.Tools; +using Sonar.Player.Application.Tools.Exceptions; +using Sonar.Player.Data; +using Sonar.Player.Domain.Entities; +using Sonar.Player.Domain.Enumerations; +using Sonar.Player.Domain.Models; +using Sonar.UserTracksManagement.ApiClient; + +namespace Sonar.Player.Application.Properties.Bitrate.Commands; + +public static class SetBitrate +{ + public record Command(string Token, Guid TrackId, string Name, Command.TrackFile File, int Bitrate) : IRequest + { + public record TrackFile(string Name, Stream Content); + }; + + public record Response(Guid TrackId); + + public class CommandHandler : IRequestHandler + { + private readonly PlayerDbContext _dbContext; + private readonly IUserTracksApiClient _userTracksApiClient; + private readonly ITrackStorage _trackStorage; + + public CommandHandler(PlayerDbContext dbContext, IUserTracksApiClient userTracksApiClient, ITrackStorage trackStorage) + { + _dbContext = dbContext; + _userTracksApiClient = userTracksApiClient; + _trackStorage = trackStorage; + } + public async Task Handle(Command request, CancellationToken cancellationToken) + { + bool isEnoughAccess = await _userTracksApiClient.IsEnoughAccessAsync( + request.Token, + request.TrackId, + cancellationToken); + + if (!isEnoughAccess) + { + throw new NotEnoughAccessException($"Not enough access to track {request.TrackId}"); + } + + await _trackStorage.DeleteTrack(request.TrackId); + + Settings.Bitrate = request.Bitrate; + var track = await _trackStorage.SaveTrack(request.TrackId, AudioFormat.FromFileName(request.File.Name), request.File.Content); + + _dbContext.Tracks.Update(track); + + return new Response(request.TrackId); + } + } +} \ No newline at end of file diff --git a/Sonar.Player/Sonar.Player.Application/Properties/Settings.cs b/Sonar.Player/Sonar.Player.Application/Properties/Settings.cs new file mode 100644 index 0000000..e139945 --- /dev/null +++ b/Sonar.Player/Sonar.Player.Application/Properties/Settings.cs @@ -0,0 +1,16 @@ +using Sonar.Player.Application.Tools; + +namespace Sonar.Player.Application.Properties; + +public class Settings +{ + private static Settings? _instance = null; + public static int Bitrate = (int) BitrateEnum.MediumBitrate; + + private Settings() { } + + public static Settings GetInstance() + { + return _instance ??= new Settings(); + } +} \ No newline at end of file diff --git a/Sonar.Player/Sonar.Player.Application/Services/TracksStorage/HlsTrackProcessor.cs b/Sonar.Player/Sonar.Player.Application/Services/TracksStorage/HlsTrackProcessor.cs index 670a5ea..1215762 100644 --- a/Sonar.Player/Sonar.Player.Application/Services/TracksStorage/HlsTrackProcessor.cs +++ b/Sonar.Player/Sonar.Player.Application/Services/TracksStorage/HlsTrackProcessor.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Sonar.Player.Application.Properties; using Sonar.Player.Application.Tools; using Sonar.Player.Domain.Entities; using Sonar.Player.Domain.Enumerations; @@ -32,7 +33,7 @@ public async Task SaveTrack(Guid id, MediaFormat format, Stream content) var arguments = FfmpegArgumentsBuilder.CreateBuilder() .GetSource(trackPath) - .SetBitrate(324) + .SetBitrate(Settings.Bitrate) .SetSegmentFilename(segmentPath) .WriteTo(infoFilePath) .Build(); diff --git a/Sonar.Player/Sonar.Player.Application/Tools/BitrateEnum.cs b/Sonar.Player/Sonar.Player.Application/Tools/BitrateEnum.cs new file mode 100644 index 0000000..658aabd --- /dev/null +++ b/Sonar.Player/Sonar.Player.Application/Tools/BitrateEnum.cs @@ -0,0 +1,8 @@ +namespace Sonar.Player.Application.Tools; + +public enum BitrateEnum : int +{ + LowBitrate = 192, + MediumBitrate = 256, + HighBitrate = 320 +} \ No newline at end of file From bf2b171d3f4e21f6cd27ec52868e82869fef1564 Mon Sep 17 00:00:00 2001 From: Patisson4 Date: Mon, 19 Sep 2022 22:49:57 +0300 Subject: [PATCH 2/2] chore: refactor --- .../Controllers/SetBitrateController.cs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs b/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs index a8c1ded..6b45419 100644 --- a/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs +++ b/Sonar.Player/Sonar.Player.Api/Controllers/SetBitrateController.cs @@ -35,12 +35,12 @@ await _mediator.Send( new SetBitrate.Command( token, trackId, - form.Name, + form.Name, new SetBitrate.Command.TrackFile( - form.File.FileName, + form.File.FileName, fileStream), - (int) BitrateEnum.LowBitrate - ), cancellationToken)); + (int)BitrateEnum.LowBitrate), + cancellationToken)); } [HttpPatch("mediumBitrate")] @@ -56,14 +56,14 @@ await _mediator.Send( new SetBitrate.Command( token, trackId, - form.Name, + form.Name, new SetBitrate.Command.TrackFile( - form.File.FileName, + form.File.FileName, fileStream), - (int) BitrateEnum.MediumBitrate - ), cancellationToken)); + (int)BitrateEnum.MediumBitrate), + cancellationToken)); } - + [HttpPatch("highBitrate")] public async Task> SetHighAsync( [FromHeader(Name = "Token")] string token, @@ -77,11 +77,11 @@ await _mediator.Send( new SetBitrate.Command( token, trackId, - form.Name, + form.Name, new SetBitrate.Command.TrackFile( - form.File.FileName, + form.File.FileName, fileStream), - (int) BitrateEnum.HighBitrate - ), cancellationToken)); + (int)BitrateEnum.HighBitrate), + cancellationToken)); } } \ No newline at end of file