Permalink
Browse files

Adição do suporte a MP3 com implementação mais estática (quase hard c…

…oded) #negativo

Importante mostrar essa implementação, pois muitas vezes é o primeiro caminho adotado, e gera muito mais trabalho do que fazer de forma mais dinâmica.
  • Loading branch information...
luizcarlosfaria committed Dec 24, 2017
1 parent 170cf1b commit 3133281c25331e71dfacd951d7353b7b5b82ebb8
@@ -15,15 +15,16 @@ public class Download
public string OriginalMediaUrl { get; set; }
public string MinioAddress { get; set; }
public DateTime Created { get; set; }
public DateTime? Finished { get; set; }
public string Title { get; set; }
public string ThumbnailUrl { get; set; }
public string Description { get; set; }
public TimeSpan Duration { get; set; }
public string DownloadUrl { get; set; }
public string VideoDownloadUrl { get; set; }
public string AudioDownloadUrl { get; set; }
public string PlayUrl { get; set; }
}
}
@@ -7,8 +7,14 @@ namespace DevWeek.Services.Downloader
public class DownloadContext : Dictionary<string, object>
{
public string MediaUrl { get { return (string)this["mediaUrl"]; } set { this["mediaUrl"] = value; } }
public string OutputFileName { get { return (string)this["outputFileName"]; } set { this["outputFileName"] = value; } }
public string OutputFilePath { get { return (string)this["outputFilePath"]; } set { this["outputFilePath"] = value; } }
public string VideoOutputFileName => $"{this.Download.Id}.mp4";
public string AudioOutputFileName => $"{this.Download.Id}.mp3";
public string VideoOutputFilePath => $"{System.IO.Path.Combine((string)this["localTemporaryFolder"], this.VideoOutputFileName)}";
public string AudioOutputFilePath => $"{System.IO.Path.Combine((string)this["localTemporaryFolder"], this.AudioOutputFileName)}";
public Download Download { get { return (Download)this["downloadObject"]; } set { this["downloadObject"] = value; } }
}
}
@@ -51,7 +51,7 @@ public async Task Insert(Download downloadToInsert)
if (downloadItemOnDB == null)
{
var downloadCollection = this.GetDownloadCollection();
await this.GetDownloadCollection().InsertOneAsync(downloadToInsert);
await this.GetDownloadCollection().InsertOneAsync(downloadToInsert);
await this.RebuildCache(downloadCollection);
}
else
@@ -9,7 +9,8 @@ public class CleanupPipelineActivity : IPipelineActivity
{
public Task ExecuteAsync(DownloadContext context)
{
System.IO.File.Delete(context.OutputFileName);
System.IO.File.Delete(context.VideoOutputFileName);
System.IO.File.Delete(context.AudioOutputFileName);
return Task.CompletedTask;
}
@@ -11,7 +11,29 @@ public class MediaDownloaderPipelineActivity : IPipelineActivity
{
public async Task ExecuteAsync(DownloadContext context)
{
var process = System.Diagnostics.Process.Start(new ProcessStartInfo("youtube-dl", $"-o {context.OutputFilePath} {context.MediaUrl}")
await VideoDownload(context);
await AudioDownload(context);
}
private static async Task VideoDownload(DownloadContext context)
{
var process = System.Diagnostics.Process.Start(new ProcessStartInfo("youtube-dl", $"-o {context.VideoOutputFilePath} {context.MediaUrl}")
{
RedirectStandardOutput = true,
RedirectStandardError = true
});
process.WaitForExit();
if (process.ExitCode != 0)
{
//Console.WriteLine(await process.StandardError.ReadToEndAsync());
//Console.WriteLine(await process.StandardOutput.ReadToEndAsync());
throw new ApplicationException("Download Failure", new Exception(await process.StandardError.ReadToEndAsync() + await process.StandardOutput.ReadToEndAsync()));
}
}
private static async Task AudioDownload(DownloadContext context)
{
var process = System.Diagnostics.Process.Start(new ProcessStartInfo("ffmpeg", $"-i {context.VideoOutputFilePath} {context.AudioOutputFilePath}")
{
RedirectStandardOutput = true,
RedirectStandardError = true

This file was deleted.

Oops, something went wrong.
@@ -20,15 +20,21 @@ public S3MediaUploaderPipelineActivity(MinioClient minio, DataService dataServic
public async Task ExecuteAsync(DownloadContext context)
{
string bucketName = (string)context["defaultBucketName"];
string audioBucketName = (string)context["audioBucketName"];
string audioFileName = System.IO.Path.GetFileName(context.AudioOutputFilePath);
await minio.PutObjectAsync(audioBucketName, audioFileName, context.AudioOutputFilePath);
await minio.PutObjectAsync(bucketName, System.IO.Path.GetFileName(context.OutputFileName), context.OutputFilePath);
string url = await minio.PresignedGetObjectAsync(bucketName, System.IO.Path.GetFileName(context.OutputFileName), (int)TimeSpan.FromHours(1).TotalSeconds);
string videobucketName = (string)context["videoBucketName"];
string videoFileName = System.IO.Path.GetFileName(context.VideoOutputFilePath);
await minio.PutObjectAsync(videobucketName, videoFileName, context.VideoOutputFilePath);
await this.dataService.Update(context.Download.Id, (update) =>
update.Combine(new[] {
update.Set(it => it.DownloadUrl, url),
update.Set(it => it.AudioDownloadUrl, $"/api/media/{audioBucketName}/download/{audioFileName}"),
update.Set(it => it.VideoDownloadUrl, $"/api/media/{videobucketName}/download/{videoFileName}"),
update.Set(it => it.PlayUrl, $"/api/media/{videobucketName}/stream/{videoFileName}"),
update.Set(it => it.Finished, DateTime.Now)
})
);
@@ -20,7 +20,7 @@ public class ResourceBootstrapService
private readonly RabbitMQ.Client.IModel model;
public string[] MongoRequiredCollections { get; set; }
public string MinioBucketName { get; set; }
public string[] MinioBucketNames { get; set; }
public string DownloadPipelineQueue { get; set; }
public string DownloadPipelineRouteKey { get; set; }
public string DownloadPipelineExchange { get; set; }
@@ -61,10 +61,13 @@ public void Check()
/// </summary>
private void CheckMinioServer()
{
bool exists = minio.BucketExistsAsync(this.MinioBucketName).GetAwaiter().GetResult();
if (exists == false)
foreach (string minioBucketName in this.MinioBucketNames)
{
minio.MakeBucketAsync(this.MinioBucketName).GetAwaiter();
bool exists = minio.BucketExistsAsync(minioBucketName).GetAwaiter().GetResult();
if (exists == false)
{
minio.MakeBucketAsync(minioBucketName).GetAwaiter();
}
}
}
@@ -56,22 +56,6 @@ public IEnumerable<Download> Get()
.Select(download =>
{
var instance = Newtonsoft.Json.JsonConvert.DeserializeObject<Download>(download);
if (string.IsNullOrWhiteSpace(instance.DownloadUrl) == false)
{
string originalDownloadUrl = instance.DownloadUrl;
UriBuilder streamUriBuilder = new UriBuilder(originalDownloadUrl);
streamUriBuilder.Host = this.Request.Host.Host;
streamUriBuilder.Port = this.Request.Host.Port ?? 80;
streamUriBuilder.Path = streamUriBuilder.Path.Insert(0, "/api/video/stream");
instance.PlayUrl = streamUriBuilder.ToString();
UriBuilder downloadUriBuilder = new UriBuilder(originalDownloadUrl);
downloadUriBuilder.Host = this.Request.Host.Host;
downloadUriBuilder.Port = this.Request.Host.Port ?? 80;
downloadUriBuilder.Path = downloadUriBuilder.Path.Insert(0, "/api/video/download");
instance.DownloadUrl = downloadUriBuilder.ToString();
}
return instance;
})
.ToArray();
@@ -9,22 +9,20 @@
namespace DevWeek.WebApp.Controllers
{
[Produces("application/json")]
[Route("api/video")]
public class VideoController : Controller
[Route("api/media")]
public class MediaController : Controller
{
private readonly Minio.MinioClient minioClient;
private string defaultBucketName;
public VideoController(Minio.MinioClient minioClient, IConfiguration configuration)
public MediaController(Minio.MinioClient minioClient, IConfiguration configuration)
{
this.minioClient = minioClient;
this.defaultBucketName = configuration.GetSection("DevWeek:S3:DefaultBucketName").Get<string>();
}
private async Task<System.IO.MemoryStream> GetVideo(string url)
private async Task<System.IO.MemoryStream> GetMedia(string bucket, string url)
{
System.IO.MemoryStream streamToReturn = new System.IO.MemoryStream();
await minioClient.GetObjectAsync(this.defaultBucketName, System.IO.Path.GetFileName(url), (stream) =>
await minioClient.GetObjectAsync(bucket, System.IO.Path.GetFileName(url), (stream) =>
{
stream.CopyTo(streamToReturn);
});
@@ -33,8 +31,8 @@ private async Task<System.IO.MemoryStream> GetVideo(string url)
}
[HttpGet("{target}/{*address}")]
public async Task<IActionResult> Stream(string target, string address)
[HttpGet("{bucket}/{target}/{*address}")]
public async Task<IActionResult> GetMedia(string target, string bucket, string address)
{
string type = null;
@@ -45,7 +43,7 @@ public async Task<IActionResult> Stream(string target, string address)
else
return this.NotFound();
System.IO.MemoryStream streamToReturn = await this.GetVideo(address);
System.IO.MemoryStream streamToReturn = await this.GetMedia(bucket, address);
var response = File(streamToReturn, type);
return response;
}
@@ -31,7 +31,8 @@
<p class="card-text text-truncate">{{item.description}}</p>
<br />
<a target="_blank" href="{{item.originalMediaUrl}}" class="card-link">Ver original</a>
<a target="_blank" ng-if="item.downloadUrl" href="{{item.downloadUrl}}" class="btn btn-primary">Download</a>
<a target="_blank" ng-if="item.audioDownloadUrl" href="{{item.audioDownloadUrl}}" class="btn btn-primary btn-sm">Baixar MP3</a>
<a target="_blank" ng-if="item.videoDownloadUrl" href="{{item.videoDownloadUrl}}" class="btn btn-primary btn-sm">Baixar MP4</a>
</div>
</div>
</div>
@@ -38,12 +38,18 @@
<object type="DevWeek.Services.ResourceBootstrapService" autowire="constructor" init-method="Check">
<property name="MinioBucketName" ref="CONFIG:DevWeek:S3:DefaultBucketName" />
<property name="DownloadPipelineQueue" ref="CONFIG:DevWeek:RabbitMQ:DownloadPipeline:Queue" />
<property name="DownloadPipelineRouteKey" ref="CONFIG:DevWeek:RabbitMQ:DownloadPipeline:RouteKey" />
<property name="DownloadPipelineExchange" ref="CONFIG:DevWeek:RabbitMQ:DownloadPipeline:Exchange" />
<property name="MongoRequiredCollections" value="media_download" />
<property name="LockTimeout" value="00:00:30" />
<property name="MongoRequiredCollections" value="media_download" />
<property name="MinioBucketNames" >
<object type="string[]" >
<constructor-arg value="2" />
<property name="[0]" ref="CONFIG:DevWeek:S3:AudioBucketName" />
<property name="[1]" ref="CONFIG:DevWeek:S3:VideoBucketName" />
</object>
</property>
<property name="DistributedLockKey" value="init-infrastructure-lock" />
</object>
@@ -56,10 +62,6 @@
<list element-type="DevWeek.Services.Downloader.IPipelineActivity, DevWeek.Contracts" >
<object type="DevWeek.Services.Downloader.EntryPointRegisterPipelineActivity, DevWeek.Services" autowire="constructor"></object>
<object type="DevWeek.Services.Downloader.MetadataDiscoveryPipelineActivity, DevWeek.Services" autowire="constructor"></object>
<object type="DevWeek.Services.Downloader.PathCombinePipelineActivity, DevWeek.Services" autowire="constructor">
<property name="Keys" value="localTemporaryFolder,outputFileName" />
<property name="OutputKey" value="outputFilePath" />
</object>
<object type="DevWeek.Services.Downloader.MediaDownloaderPipelineActivity, DevWeek.Services" autowire="constructor"></object>
<object type="DevWeek.Services.Downloader.S3MediaUploaderPipelineActivity, DevWeek.Services" autowire="constructor"></object>
<object type="DevWeek.Services.Downloader.CleanupPipelineActivity, DevWeek.Services" autowire="constructor"></object>
@@ -68,7 +70,8 @@
<property name="Context">
<dictionary key-type="string" value-type="object">
<entry key="localTemporaryFolder" value-ref="CONFIG:DevWeek:LocalTemporaryFolder" />
<entry key="defaultBucketName" value-ref="CONFIG:DevWeek:S3:DefaultBucketName" />
<entry key="audioBucketName" value-ref="CONFIG:DevWeek:S3:AudioBucketName" />
<entry key="videoBucketName" value-ref="CONFIG:DevWeek:S3:VideoBucketName" />
</dictionary>
</property>
</object>
@@ -1,8 +1,9 @@
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
RUN apt-get update && apt-get install python2.7-minimal -y && cp /usr/bin/python2.7 /usr/bin/python
RUN apt-get update && apt-get install libav-tools python2.7-minimal -y && cp /usr/bin/python2.7 /usr/bin/python
RUN curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl && chmod a+rx /usr/local/bin/youtube-dl
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY *.sln ./
@@ -60,7 +60,6 @@ static void Main(string[] args)
var context = new DownloadContext()
{
MediaUrl = messageObject.OriginalMediaUrl,
OutputFileName = $"{Guid.NewGuid().ToString("N")}.mp4",
Download = messageObject
};
@@ -29,7 +29,8 @@
"Endpoint": "s3:9000",
"AccessKey": "Zu8VgBoZMU2xcmOEeS70",
"SecretKey": "xvnjYyFQyFs44iuUagi4kTHiOGvlK1PiX64LiwOy",
"DefaultBucketName": "videos"
"AudioBucketName": "audio",
"VideoBucketName": "video"
},
"MongoDB": {
"ConnectionString": "mongodb://mongouser:eprPs2UEJ239RvH7SicPkcFbkTQoa8@mongodb:27017/admin",

0 comments on commit 3133281

Please sign in to comment.