Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 30 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
# SharpGrabber
<img src="./assets/icon.png" alt="SharpGrabber" width="64"/>

A **.NET Standard** library for grabbing information and
downloading from top media providers such as **YouTube**, **Instagram** etc.

## Features
- Grabs useful information about media such as length, title, author and many more.
- Deciphers secure *YouTube* videos optionally.
- Extracts direct links to all available qualities.
- Extracts images and thumbnails.
- Supports *asynchronous* operations.
This project consists of several connected sub-projects:
- `SharpGrabber` is a *.NET Standard* library for crawling into top media provider websites such as **YouTube**, **Instagram** etc. in order to grab information and return direct links of the audio/video files.
- `SharpGrabber.Converter` is a *.NET Standard* library based on `ffmpeg` to join audio and video streams. This is particularly useful when grabbing high quality *YouTube* media that might be separated into audio and video files.
- `SharpGrabber.Desktop` A cross-platform desktop application
which utilizes both mentioned libraries to expose their functionality for desktop end-users.

### Supported Providers
The following providers are currently supported with the option
Expand All @@ -18,13 +14,25 @@ to easily add more or even override part of grabbing algorithm with your own cod
- YouTube
- Instagram

## Installation
Install *SharpGrabber* automatically using NuGet package manager.
## Features
#### SharpGrabber Library
- Grabs useful information about media such as length, title, author and many more.
- Deciphers secure *YouTube* videos optionally.
- Extracts direct links to all available qualities.
- Extracts images and thumbnails.
- Supports *asynchronous* operations.

#### SharpGrabber.Desktop Application
- Displays information obtained by the `SharpGrabber` library and downloads the resolved direct links.
- Uses `SharpGrabber.Converter` to merge YouTube separated audio and video streams into complete media files.

## SharpGrabber Installation
Include *SharpGrabber* library in your own .NET projects.

### Install via NuGet
Install-Package DotNetTools.SharpGrabber -Version 1.0.0

## Usage Example
## SharpGrabber Usage Example

### Download specifically from a provider

Expand All @@ -38,11 +46,19 @@ Install *SharpGrabber* automatically using NuGet package manager.
var result = await grabber.GrabAsync(new Uri("<Target Link>"));
IList<IGrabbed> grabbedResources = result.Resources;

## SharpGrabber.Desktop
Requirements of the cross-platform desktop application to run and operate correctly:
- .NET Core 2.1 or higher (.NET Framework 4.6.1 or higher)
- Shared libraries of *ffmpeg* copied into `ffmpeg` directory alongside app executable files for media conversion support.
- On Windows, you may download the latest <a href="https://ffmpeg.zeranoe.com/builds/">Zeranoe ffmpeg build</a>.

<img src="./assets/SharpGrabberDesktop-ScreenShot-1.png" alt="SharpGrabber.Desktop application" />

## Roadmap
This project is very much in progress and the following features
are top priority:
- Conversion support (especially useful for high quality YouTube videos)
- .NET Core demo app
- Support for Android
- Accelerate downloads in the desktop app (like a download manager)
- Support for more media providers

## Support
Expand Down
19 changes: 16 additions & 3 deletions SharpGrabber.sln
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
Microsoft Visual Studio Solution File, Format Version 12.00

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29418.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetTools.SharpGrabber", "src\DotNetTools.SharpGrabber\DotNetTools.SharpGrabber.csproj", "{F2CB23B0-E878-4CDE-9F29-C3B8E915125B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGrabber", "src\SharpGrabber\SharpGrabber.csproj", "{F2CB23B0-E878-4CDE-9F29-C3B8E915125B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetTools.SharpGrabber.Tests", "tests\DotNetTools.SharpGrabber.Tests\DotNetTools.SharpGrabber.Tests.csproj", "{B597E685-3509-435E-B11A-BC5A151051CE}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGrabber.Tests", "tests\DotNetTools.SharpGrabber.Tests\SharpGrabber.Tests.csproj", "{B597E685-3509-435E-B11A-BC5A151051CE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGrabber.Converter", "src\SharpGrabber.Converter\SharpGrabber.Converter.csproj", "{C0A29188-D1FA-4F00-A77A-D1B17FD992FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGrabber.Desktop", "src\SharpGrabber.Desktop\SharpGrabber.Desktop.csproj", "{F57085EC-1886-4671-A8B2-7EAAA4EE1871}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -20,6 +25,14 @@ Global
{B597E685-3509-435E-B11A-BC5A151051CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B597E685-3509-435E-B11A-BC5A151051CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B597E685-3509-435E-B11A-BC5A151051CE}.Release|Any CPU.Build.0 = Release|Any CPU
{C0A29188-D1FA-4F00-A77A-D1B17FD992FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0A29188-D1FA-4F00-A77A-D1B17FD992FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0A29188-D1FA-4F00-A77A-D1B17FD992FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0A29188-D1FA-4F00-A77A-D1B17FD992FF}.Release|Any CPU.Build.0 = Release|Any CPU
{F57085EC-1886-4671-A8B2-7EAAA4EE1871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F57085EC-1886-4671-A8B2-7EAAA4EE1871}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F57085EC-1886-4671-A8B2-7EAAA4EE1871}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F57085EC-1886-4671-A8B2-7EAAA4EE1871}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Binary file added assets/SharpGrabberDesktop-ScreenShot-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions src/SharpGrabber.Converter/FFMpegHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using FFmpeg.AutoGen;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace DotNetTools.SharpGrabber.Converter
{
internal static class FFMpegHelper
{
public static unsafe string av_strerror(int error)
{
var bufferSize = 1024;
var buffer = stackalloc byte[bufferSize];
ffmpeg.av_strerror(error, buffer, (ulong)bufferSize);
var message = Marshal.PtrToStringAnsi((IntPtr)buffer);
return message;
}

public static int ThrowOnError(this int result)
{
if (result < 0)
throw new ApplicationException(av_strerror(result));
return result;
}
}
}
51 changes: 51 additions & 0 deletions src/SharpGrabber.Converter/IOContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using FFmpeg.AutoGen;
using System;
using System.Collections.Generic;
using System.Text;

namespace DotNetTools.SharpGrabber.Converter
{
unsafe sealed class IOContext : IDisposable
{
#region Fields
private AVIOContext* _ioContext;
private bool usedAvioOpen;
#endregion

#region Properties
public AVIOContext* Pointer => _ioContext;
#endregion

#region Constructor
public IOContext(AVIOContext* ioContext)
{
_ioContext = ioContext;
}

public IOContext(string path, int flags)
{
usedAvioOpen = true;
AVIOContext* ioContext = null;
ffmpeg.avio_open2(&ioContext, path, flags, null, null).ThrowOnError();
_ioContext = ioContext;
}

public IOContext(Uri uri, int flags) : this(uri.IsFile ? uri.LocalPath : uri.ToString(), flags) { }
#endregion

#region Methods
public void Dispose()
{
if (_ioContext != null)
{
var ioContext = _ioContext;
if (usedAvioOpen)
ffmpeg.avio_close(ioContext);
else
ffmpeg.avio_context_free(&ioContext);
_ioContext = null;
}
}
#endregion
}
}
Loading