C# Download the sound of a youtube video - c#

I can download a video from youtube but I want the sound only. How can I do that?
Code I have for downloading the video (Using VideoLibrary):
YouTube youtube = YouTube.Default;
Video vid = youtube.GetVideo(txt_youtubeurl.Text);
System.IO.File.WriteAllBytes(source + vid.FullName, vid.GetBytes());

Install the NuGet packages: MediaToolkit and VideoLibrary, it will allow you to do the conversion by file extension.
var source = #"<your destination folder>";
var youtube = YouTube.Default;
var vid = youtube.GetVideo("<video url>");
File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
var inputFile = new MediaFile { Filename = source + vid.FullName };
var outputFile = new MediaFile { Filename = $"{source + vid.FullName}.mp3" };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}

The above code works awesome you don't need to download the video first I created this procedure so when rookies like myself see this makes it easier to use.
You need the nuget packages MediaToolkit and VideoLibrary.
example url: https://www.youtube.com/watch?v=lzm5llVmR2E
example path just needs a path to save file to.
just add the name of the mp3 file to save
Hope this helps someone I have tested this code;
private void SaveMP3(string SaveToFolder, string VideoURL, string MP3Name)
{
var source = #SaveToFolder;
var youtube = YouTube.Default;
var vid = youtube.GetVideo(VideoURL);
File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
var inputFile = new MediaFile { Filename = source + vid.FullName };
var outputFile = new MediaFile { Filename = $"{MP3Name}.mp3" };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}
}

based on this topic, i have developed a simple and dumb program to Download a youtube playlist. Hope this helps someone. It's just a Main.cs file: Youtube Playlist Downloader - Mp4 & Mp3

Ok found a better way the above code didn't normalize the audio posting it for others.
First Add Nuget package: https://www.nuget.org/packages/NReco.VideoConverter/
To Convert MP4 to MP3
// Client
var client = new YoutubeClient();
var videoId = NormalizeVideoId(txtFileURL.Text);
var video = await client.GetVideoAsync(videoId);
var streamInfoSet = await client.GetVideoMediaStreamInfosAsync(videoId);
// Get the best muxed stream
var streamInfo = streamInfoSet.Muxed.WithHighestVideoQuality();
// Compose file name, based on metadata
var fileExtension = streamInfo.Container.GetFileExtension();
var fileName = $"{video.Title}.{fileExtension}";
// Replace illegal characters in file name
fileName = RemoveIllegalFileNameChars(fileName);
tmrVideo.Enabled = true;
// Download video
txtMessages.Text = "Downloading Video please wait ... ";
//using (var progress = new ProgressBar())
await client.DownloadMediaStreamAsync(streamInfo, fileName);
// Add Nuget package: https://www.nuget.org/packages/NReco.VideoConverter/ To Convert MP4 to MP3
if (ckbAudioOnly.Checked)
{
var Convert = new NReco.VideoConverter.FFMpegConverter();
String SaveMP3File = MP3FolderPath + fileName.Replace(".mp4", ".mp3");
Convert.ConvertMedia(fileName, SaveMP3File, "mp3");
//Delete the MP4 file after conversion
File.Delete(fileName);
LoadMP3Files();
txtMessages.Text = "File Converted to MP3";
tmrVideo.Enabled = false;
txtMessages.BackColor = Color.White;
if (ckbAutoPlay.Checked) { PlayFile(SaveMP3File); }
return;
}

I like the idea of using a method. I tried SaveMP3() but it had some problems.
This worked for me: `
private void SaveMP3(string SaveToFolder, string VideoURL, string MP3Name)
{
string source = SaveToFolder;
var youtube = YouTube.Default;
var vid = youtube.GetVideo(VideoURL);
string videopath = Path.Combine(source, vid.FullName);
File.WriteAllBytes(videopath, vid.GetBytes());
var inputFile = new MediaFile { Filename = Path.Combine(source, vid.FullName) };
var outputFile = new MediaFile { Filename = Path.Combine(source , $"{MP3Name}.mp3") };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}
File.Delete(Path.Combine(source, vid.FullName));
}
`

Related

How to extract all pages and attachments from PDF to PNG

I am trying to create a process in .NET to convert a PDF and all it's pages + attachments to PNGs. I am evaluating libraries and came across PDFiumSharp but it is not working for me. Here is my code:
string Inputfile = "input.pdf";
string OutputFolder = "Output";
string fileName = Path.GetFileNameWithoutExtension(Inputfile);
using (PdfDocument doc = new PdfDocument(Inputfile))
{
for (int i = 0; i < doc.Pages.Count; i++)
{
var page = doc.Pages[i];
using (var bitmap = new PDFiumBitmap((int)page.Width, (int)page.Height, false))
{
page.Render(bitmap);
var targetFile = Path.Combine(OutputFolder, fileName + "_" + i + ".png");
bitmap.Save(targetFile);
}
}
}
When I run this code, I get this exception:
screenshot of exception
Does anyone know how to fix this? Also does PDFiumSharp support extracting PDF attachments? If not, does anyone have any other ideas on how to achieve my goal?
PDFium does not look like it supports extracting PDF attachments. If you want to achieve your goal, then you can take a look at another library that supports both extracting PDF attachments as well as converting PDFs to PNGs.
I am an employee of the LEADTOOLS PDF SDK which you can try out via these 2 nuget packages:
https://www.nuget.org/packages/Leadtools.Pdf/
https://www.nuget.org/packages/Leadtools.Document.Sdk/
Here is some code that will convert a PDF + all attachments in the PDF to separate PNGs in an output directory:
SetLicense();
cache = new FileCache { CacheDirectory = "cache" };
List<LEADDocument> documents = new List<LEADDocument>();
if (!Directory.Exists(OutputDir))
Directory.CreateDirectory(OutputDir);
using var document = DocumentFactory.LoadFromFile("attachments.pdf", new LoadDocumentOptions { Cache = cache, LoadAttachmentsMode = DocumentLoadAttachmentsMode.AsAttachments });
if (document.Pages.Count > 0)
documents.Add(document);
foreach (var attachment in document.Attachments)
documents.Add(document.LoadDocumentAttachment(new LoadAttachmentOptions { AttachmentNumber = attachment.AttachmentNumber }));
ConvertDocuments(documents, RasterImageFormat.Png);
And the ConvertDocuments method:
static void ConvertDocuments(IEnumerable<LEADDocument> documents, RasterImageFormat imageFormat)
{
using var converter = new DocumentConverter();
using var ocrEngine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD);
ocrEngine.Startup(null, null, null, null);
converter.SetOcrEngineInstance(ocrEngine, false);
converter.SetDocumentWriterInstance(new DocumentWriter());
foreach (var document in documents)
{
var name = string.IsNullOrEmpty(document.Name) ? "Attachment" : document.Name;
string outputFile = Path.Combine(OutputDir, $"{name}.{RasterCodecs.GetExtension(imageFormat)}");
int count = 1;
while (File.Exists(outputFile))
outputFile = Path.Combine(OutputDir, $"{name}({count++}).{RasterCodecs.GetExtension(imageFormat)}");
var jobData = new DocumentConverterJobData
{
Document = document,
Cache = cache,
DocumentFormat = DocumentFormat.User,
RasterImageFormat = imageFormat,
RasterImageBitsPerPixel = 0,
OutputDocumentFileName = outputFile,
};
var job = converter.Jobs.CreateJob(jobData);
converter.Jobs.RunJob(job);
}
}

Xamarin.forms ImageSource.FromFile doesn't work

I'm using Xam.Plugin.Media to take a picture .
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions()
{
Directory = "attachments",
Name = fileName,
CompressionQuality = 35
});
cam.Source = ImageSource.FromFile(file.Path);
above code does work !
file path is (file.Path):
/var/mobile/Containers/Data/Application/F3997E36-78EB-41AF-A37F-FC794BAF30EC/Documents/attachments/13c8ac4e57734a36bded2c2694e27495.jpg
but this code does not show picture in an Image control
var q = "/var/mobile/Containers/Data/Application/F3997E36-78EB-41AF-A37F-FC794BAF30EC/Documents/attachments/13c8ac4e57734a36bded2c2694e27495.jpg"
cam.Source = ImageSource.FromFile(q);
On iOS, this is the way to load file you saved before. This is because the system regenerate UDID every time the app relaunch.
public Stream LoadSampleStream(string filename) {
try
{
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath = Path.Combine(documentsPath, "Sample", filename);
return new FileStream(filePath, FileMode.Open);
}
catch(Exception ex) {
return null;
}
}
You need to save photo in gallery. When your user takes a photo it will still store temporary data, but also if needed make a copy to the public gallery
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
SaveToAlbum = true
});
Get the public album path
var aPpath = file.AlbumPath;
Get private path
var path = file.Path;

Splitting a video in four files in C#

I am doing a research of how to split a video in four fragments. I have seen a lot of solutions and libraries. I was looking at this library:
https://github.com/AydinAdn/MediaToolkit
And this is the code for splitting the video
var inputFile = new MediaFile {Filename = #"C:\Path\To_Video.flv"};
var outputFile = new MediaFile {Filename = #"C:\Path\To_Save_ExtractedVideo.flv"};
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
var options = new ConversionOptions();
// This example will create a 25 second video, starting from the
// 30th second of the original video.
//// First parameter requests the starting frame to cut the media from.
//// Second parameter requests how long to cut the video.
options.CutMedia(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(25));
engine.Convert(inputFile, outputFile, options);
}
The code is splitting just one fragment. Is there a way to split it in four fragments?
Kind regards
PS: the solution must be in C# and already have seen the Directshow solution.
It works well for me, but I'll fix the algorithm, because I'm missing the final video following, the code I have at the moment is this:
static void Main(string[] args)
{
using (var engine = new Engine())
{
string file = #"C:\Users\wilso\Downloads\IZA - Meu Talismã.mp4";
var inputFile = new MediaFile { Filename = file };
engine.GetMetadata(inputFile);
var outputName = #"C:\Users\wilso\Downloads\output";
var outputExtension = ".mp4";
double Duration = inputFile.Metadata.Duration.TotalSeconds;
double currentPosition = 0;
int contador = 0;
while (currentPosition < Duration)
{
currentPosition = contador * 30;
contador++;
var options = new ConversionOptions();
var outputFile = new MediaFile(outputName + contador.ToString("00") + outputExtension);
options.CutMedia(TimeSpan.FromSeconds(currentPosition), TimeSpan.FromSeconds(30));
engine.Convert(inputFile, outputFile, options);
}
}
}
I haven't used this library before but this is how I would go about it.
var inputFile = new MediaFile {Filename = #"C:\Path\To_Video.flv"};
var outputName = "C:\Path\To_Save_ExtractedVideo";
var outputExtension = ".flv";
double t = inputFile.Length/4; //length of parts -- need to use method to get file playtime length
for(int i=0;i<4;i++){
var engine = new Engine()
engine.GetMetadata(inputFile);
var options = new ConversionOptions();
// This example will create a 25 second video, starting from the
// 30th second of the original video.
//// First parameter requests the starting frame to cut the media from.
//// Second parameter requests how long to cut the video.
options.CutMedia(TimeSpan.FromSeconds(30 + (i*int.Parse(t))), TimeSpan.FromSeconds((i+1)*int.Parse(t)));
engine.Convert(inputFile, $"{outputName}_{i.ToString()}{outputExtension}, options);
engine.Destroy(); // Need to destroy object or close inputstream. Whichever the library offers
}
}

SSIS 2015 Script task convert text file to UTF8 in C# or VB

I want to convert my resulting txt file into a UTF8 formatted file so I can load it into my Azure SQL DW via Polybase. It is required the source file be in UTF8.
MSDN has an "IO Streaming example" HERE works perfectly for a single job. I am trying to architect an SSIS solution for around 30 tables though. I believe using this method would cause a race condition where the PS script will be locked by 1 SSIS package when another SSIS package needs it.
I am a sql dev, not a .NET dev so please forgive me. How would one convert the above to an SSIS C# Script task assuming I know how to pass parameters into the Script task?
PowerShell Code from MSDN
#Static variables
$ascii = [System.Text.Encoding]::ASCII
$utf16le = [System.Text.Encoding]::Unicode
$utf8 = [System.Text.Encoding]::UTF8
$ansi = [System.Text.Encoding]::Default
$append = $False
#Set source file path and file name
$src = [System.IO.Path]::Combine("<MySrcFolder>","<MyUtf8stage>.txt")
#Set source file encoding (using list above)
$src_enc = $ascii
#Set target file path and file name
$tgt = [System.IO.Path]::Combine("<MyDestFolder>","<MyFinalstage>.txt")
#Set target file encoding (using list above)
$tgt_enc = $utf8
$read = New-Object System.IO.StreamReader($src,$src_enc)
$write = New-Object System.IO.StreamWriter($tgt,$append,$tgt_enc)
while ($read.Peek() -ne -1)
{
$line = $read.ReadLine();
$write.WriteLine($line);
}
$read.Close()
$read.Dispose()
$write.Close()
$write.Dispose()
Update
I found a similar post which I was able to tweak to my needs, I swear I searched high and low before posting. Anyway here is what IS working for me. If you see anyway to improve it please share:
public void Main()
{
//$Package::SourceSQLObject = tablename
//$Package::StageFile_DestinationFolderPath = rootpath eg "C:\temp\"
string path = (string)Dts.Variables["$Package::StageFile_DestinationFolderPath"].Value;
string name = (string)Dts.Variables["$Package::SourceSQLObject"].Value;
string from = Path.Combine(path, name) + ".csv";
string to = Path.ChangeExtension(from, "txt");
Dts.Log("Starting " + to.ToUpper(), 0, null);
using (StreamReader reader = new StreamReader(from, Encoding.ASCII, false, 10))
using (StreamWriter writer = new StreamWriter(to, false, Encoding.UTF8, 10))
{
while (reader.Peek() >= 0)
{
writer.WriteLine(reader.ReadLine());
}
}
Dts.TaskResult = (int)ScriptResults.Success;
Your code indicates that your are trying to convert an ASCII file to UTF-8 however that article also states the following:
As UTF-8 uses the same character encoding as ASCII PolyBase will also
support loading data that is ASCII encoded.
So my advice to you is to try the file first with Polybase, check for any conversion issues before you spend any time trying to convert the files.
var mySrcFolder = ""; // something from user variables?
var myUtf8stage = ""; // something from user variables?
var myFinalstage = ""; // something from user variables?
// Static variables
var ascii = System.Text.Encoding.ASCII;
var utf16le = System.Text.Encoding.Unicode;
var utf8 = System.Text.Encoding.UTF8;
var ansi = System.Text.Encoding.Default;
var append = false;
// Set source file path and file name
var src = System.IO.Path.Combine(
mySrcFolder,
String.Format("{0}.txt", myUtf8stage));
// Set source file encoding (using list above)
var src_enc = ascii;
// Set target file path and file name
var tgt = System.IO.Path.Combine(
mySrcFolder,
String.Format("{0}.txt", myFinalstage));
// Set target file encoding (using list above)
var tgt_enc = utf8;
using (var read = new System.IO.StreamReader(src, src_enc))
using (var write = new System.IO.StreamWriter(tgt, append, tgt_enc))
{
while (read.Peek() != -1)
{
var line = read.ReadLine();
write.WriteLine(line);
}
}
public void Main()
{
//$Package::SourceSQLObject = tablename
//$Package::StageFile_DestinationFolderPath = rootpath eg "C:\temp\"
string path = (string)Dts.Variables["$Package::StageFile_DestinationFolderPath"].Value;
string name = (string)Dts.Variables["$Package::SourceSQLObject"].Value;
string from = Path.Combine(path, name) + ".csv";
string to = Path.ChangeExtension(from, "txt");
Dts.Log("Starting " + to.ToUpper(), 0, null);
using (StreamReader reader = new StreamReader(from, Encoding.ASCII, false, 10))
using (StreamWriter writer = new StreamWriter(to, false, Encoding.UTF8, 10))
{
while (reader.Peek() >= 0)
{
writer.WriteLine(reader.ReadLine());
}
}
Dts.TaskResult = (int)ScriptResults.Success;

retrieving a matched name video in MediaElement control WPF

i want to play the video which name is entered in text box. But it does not play the exact video it plays the first video present in folder. any help please..
Code
String vid_name = data.Text;
string complete_name = vid_name.ToLower() + ".mp4";
string root = System.IO.Path.GetDirectoryName("D:/abc");
string[] supportedExtensions = new[] { ".mp4" };
var files = Directory.GetFiles(Path.Combine(root, "Videos"), "*.*").Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower()));
List<VideosDetail> videos = new List<VideosDetail>();
VideosDetail id;
foreach (var file in files)
{
id = new VideosDetail()
{
Path = file,
FileName = Path.GetFileName(file),
Extension = Path.GetExtension(file)
};
FileInfo fi = new FileInfo(file);
id.FileName = fi.Name;
id.Size = fi.Length;
videos.Add(id);
if (id.FileName == complete_name)
{
VideoList.ItemsSource = videos; //**Problem comes here
}
else
{
MessageBox.Show("no such video is available. ");
}
}
Since videos is a List, the line
VideoList.ItemsSource = videos;
Points to all the videos in the folder (up to the one that actually matches the filename you entered). Hence, the unwanted result.
You should probably pass the index of the video in your list, something like:
player.Source = videos[x];
Hope this helps!

Categories