| El desarrollo de este proyecto está completamente financiado por la comunidad. ¡Considere donar para apoyar! |

YouTubeExplode es una biblioteca que proporciona una interfaz para consultar metadatos de videos de YouTube, listas de reproducción y canales, así como para resolver y descargar transmisiones de video y pistas de subtítulos cerradas. Detrás de una capa de abstracción, esta biblioteca funciona raspando datos de página sin procesar y explotando puntos finales internos de ingeniería inversa.
¿Interesado en el funcionamiento interno de esta biblioteca? Consulte el artículo de Investigación inversa de YouTube.
Paquetes de extensión :
Al usar este proyecto o su código fuente, para cualquier propósito y, en cualquier forma o forma, usted otorga su acuerdo implícito a todas las siguientes afirmaciones:
Para obtener más información sobre la guerra y cómo puede ayudar, haga clic aquí. ¡Gloria a Ucrania! ?
dotnet add package YoutubeExplode 
YouTubeExplode expone su funcionalidad a través de un solo punto de entrada: la clase YoutubeClient . Cree una instancia de esta clase y use las operaciones proporcionadas en Videos , Playlists , Channels y propiedades Search para enviar solicitudes.
Para recuperar los metadatos asociados con un video de YouTube, llame Videos.GetAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
// You can specify either the video URL or its ID
var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs" ;
var video = await youtube . Videos . GetAsync ( videoUrl ) ;
var title = video . Title ; // "Collections - Blender 2.80 Fundamentals"
var author = video . Author . ChannelTitle ; // "Blender"
var duration = video . Duration ; // 00:07:20 Cada video de YouTube tiene una serie de transmisiones disponibles, que difieren en contenedores, calidad de video, tasa de bits, cuadros y otros parámetros. Además, las transmisiones se dividen aún más en 3 categorías en función de su contenido:
Advertencia : las transmisiones muxed contienen audio y video, pero estas transmisiones son de calidad limitadas (hasta 720p30). Para descargar el video en la calidad más alta disponible, deberá resolver las mejores transmisiones de solo audio y solo videos por separado y luego muxizarlos. El proceso de muxing se puede realizar utilizando FFMPEG con la ayuda del paquete YouTubeExPlode.Converter .
ADVERTENCIA : las transmisiones muxed están desaprobadas por YouTube y no se garantiza que estén disponibles para cada video. Si es posible, evite confiar demasiado en ellos y, en su lugar, realice Muxing manualmente utilizando las transmisiones proporcionadas solo de audio y solo video.
Puede solicitar el manifiesto que enumera todas las transmisiones disponibles para un video en particular llamando a Videos.Streams.GetManifestAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs" ;
var streamManifest = await youtube . Videos . Streams . GetManifestAsync ( videoUrl ) ;Una vez que se obtiene el manifiesto, puede filtrar a través de las transmisiones e identificar las que le interesan:
using YoutubeExplode ;
using YoutubeExplode . Videos . Streams ;
// ...
// Get the highest bitrate audio-only stream
var streamInfo = streamManifest . GetAudioOnlyStreams ( ) . GetWithHighestBitrate ( ) ;
// ...or the highest quality MP4 video-only stream
var streamInfo = streamManifest
. GetVideoOnlyStreams ( )
. Where ( s => s . Container == Container . Mp4 )
. GetWithHighestVideoQuality ( ) Finalmente, puede resolver la transmisión real representada por los metadatos especificados usando Videos.Streams.GetAsync(...) o descargarlo directamente en un archivo con Videos.Streams.DownloadAsync(...) :
// ...
// Get the actual stream
var stream = await youtube . Videos . Streams . GetAsync ( streamInfo ) ;
// Download the stream to a file
await youtube . Videos . Streams . DownloadAsync ( streamInfo , $ "video. { streamInfo . Container } " ) ;ADVERTENCIA : Si bien la propiedad
Urlen los metadatos de la corriente se puede utilizar para acceder al contenido subyacente, necesita una serie de solicitudes HTTP cuidadosamente elaboradas para hacerlo. Se recomienda usarVideos.Streams.GetAsync(...)oVideos.Streams.DownloadAsync(...)en su lugar, ya que realizarán todo el trabajo pesado para usted.
Los subtítulos cerrados se pueden descargar de manera similar a las transmisiones de medios. Para obtener la lista de pistas de subtítulos cerradas disponibles, llame a Videos.ClosedCaptions.GetManifestAsync(...)
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var videoUrl = "https://youtube.com/watch?v=u_yIGGhubZs" ;
var trackManifest = await youtube . Videos . ClosedCaptions . GetManifestAsync ( videoUrl ) ;Luego recupere los metadatos para una pista en particular:
// ...
// Find closed caption track in English
var trackInfo = trackManifest . GetByLanguage ( "en" ) ; Finalmente, use Videos.ClosedCaptions.GetAsync(...) para obtener el contenido real de la pista:
// ...
var track = await youtube . Videos . ClosedCaptions . GetAsync ( trackInfo ) ;
// Get the caption displayed at 0:35
var caption = track . GetByTime ( TimeSpan . FromSeconds ( 35 ) ) ;
var text = caption . Text ; // "collection acts as the parent collection" También puede descargar la pista de subtítulos cerradas en el formato de archivo SRT con Videos.ClosedCaptions.DownloadAsync(...) :
// ...
await youtube . Videos . ClosedCaptions . DownloadAsync ( trackInfo , "cc_track.srt" ) ; Puede obtener los metadatos asociados con una lista de reproducción de YouTube llamando al método Playlists.GetAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6" ;
var playlist = await youtube . Playlists . GetAsync ( playlistUrl ) ;
var title = playlist . Title ; // "First Steps - Blender 2.80 Fundamentals"
var author = playlist . Author . ChannelTitle ; // "Blender" Para que los videos se incluyan en una lista de reproducción, llame Playlists.GetVideosAsync(...) :
using YoutubeExplode ;
using YoutubeExplode . Common ;
var youtube = new YoutubeClient ( ) ;
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6" ;
// Get all playlist videos
var videos = await youtube . Playlists . GetVideosAsync ( playlistUrl ) ;
// Get only the first 20 playlist videos
var videosSubset = await youtube . Playlists . GetVideosAsync ( playlistUrl ) . CollectAsync ( 20 ) ;También puede enumerar los videos iterativamente sin esperar a que se cargue la lista completa:
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6" ;
await foreach ( var video in youtube . Playlists . GetVideosAsync ( playlistUrl ) )
{
var title = video . Title ;
var author = video . Author ;
} Si necesita un control preciso sobre cuántas solicitudes envía a YouTube, use Playlists.GetVideoBatchesAsync(...) que devuelve videos envueltos en lotes:
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var playlistUrl = "https://youtube.com/playlist?list=PLa1F2ddGya_-UvuAqHAksYnB0qL9yWDO6" ;
// Each batch corresponds to one request
await foreach ( var batch in youtube . Playlists . GetVideoBatchesAsync ( playlistUrl ) )
{
foreach ( var video in batch . Items )
{
var title = video . Title ;
var author = video . Author ;
}
}Nota : Puede crear ID de lista de reproducción para obtener listas de reproducción especiales generadas automáticamente, como mezclas de música, cargas populares de canales, videos me gustan y más. Vea esta referencia para obtener más información.
Puede obtener los metadatos asociados con un canal de YouTube llamando al método Channels.GetAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg" ;
var channel = await youtube . Channels . GetAsync ( channelUrl ) ;
var title = channel . Title ; // "Blender" También puede obtener los metadatos del canal por nombre de usuario o URL de perfil con Channels.GetByUserAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var channelUrl = "https://youtube.com/user/BlenderFoundation" ;
var channel = await youtube . Channels . GetByUserAsync ( channelUrl ) ;
var id = channel . Id ; // "UCSMOQeBJ2RAnuFungnQOxLg" Para obtener los metadatos del canal mediante Slug o URL personalizado heredado, use Channels.GetBySlugAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var channelUrl = "https://youtube.com/c/BlenderFoundation" ;
var channel = await youtube . Channels . GetBySlugAsync ( channelUrl ) ;
var id = channel . Id ; // "UCSMOQeBJ2RAnuFungnQOxLg" Para obtener los metadatos del canal por mango o URL personalizada, use Channels.GetByHandleAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
var channelUrl = "https://youtube.com/@BeauMiles" ;
var channel = await youtube . Channels . GetByHandleAsync ( channelUrl ) ;
var id = channel . Id ; // "UCm325cMiw9B15xl22_gr6Dw" Para obtener la lista de videos cargados por un canal, llame a Channels.GetUploadsAsync(...) :
using YoutubeExplode ;
using YoutubeExplode . Common ;
var youtube = new YoutubeClient ( ) ;
var channelUrl = "https://youtube.com/channel/UCSMOQeBJ2RAnuFungnQOxLg" ;
var videos = await youtube . Channels . GetUploadsAsync ( channelUrl ) ; Puede ejecutar una consulta de búsqueda llamando al método Search.GetResultsAsync(...) . Cada resultado de la búsqueda puede representar un video, una lista de reproducción o un canal, por lo que debe aplicar la coincidencia de patrones para manejar los casos correspondientes:
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
await foreach ( var result in youtube . Search . GetResultsAsync ( "blender tutorials" ) )
{
// Use pattern matching to handle different results (videos, playlists, channels)
switch ( result )
{
case VideoSearchResult video :
{
var id = video . Id ;
var title = video . Title ;
var duration = video . Duration ;
break ;
}
case PlaylistSearchResult playlist :
{
var id = playlist . Id ;
var title = playlist . Title ;
break ;
}
case ChannelSearchResult channel :
{
var id = channel . Id ;
var title = channel . Title ;
break ;
}
}
} Para limitar los resultados a un tipo específico, use Search.GetVideosAsync(...) , Search.GetPlaylistsAsync(...) o Search.GetChannelsAsync(...) ::
using YoutubeExplode ;
using YoutubeExplode . Common ;
var youtube = new YoutubeClient ( ) ;
var videos = await youtube . Search . GetVideosAsync ( "blender tutorials" ) ;
var playlists = await youtube . Search . GetPlaylistsAsync ( "blender tutorials" ) ;
var channels = await youtube . Search . GetChannelsAsync ( "blender tutorials" ) ; De manera similar a las listas de reproducción, también puede enumerar los resultados en lotes llamando Search.GetResultBatchesAsync(...) :
using YoutubeExplode ;
var youtube = new YoutubeClient ( ) ;
// Each batch corresponds to one request
await foreach ( var batch in youtube . Search . GetResultBatchesAsync ( "blender tutorials" ) )
{
foreach ( var result in batch . Items )
{
switch ( result )
{
case VideoSearchResult videoResult :
{
// ...
}
case PlaylistSearchResult playlistResult :
{
// ...
}
case ChannelSearchResult channelResult :
{
// ...
}
}
}
} Puede acceder a videos privados y listas de reproducción proporcionando cookies que corresponden a una cuenta de YouTube preautenticada. Para hacer eso, cree una instancia de YoutubeClient utilizando un constructor que acepte IReadOnlyList<Cookie> :
using YoutubeExplode ;
// Perform authentication and extract cookies
var cookies = .. . ;
// Cookie collection must be of type IReadOnlyList<System.Net.Cookie>
var youtube = new YoutubeClient ( cookies ) ;Para realizar realmente la autenticación, puede usar un navegador integrado como WebView para navegar al usuario a la página de inicio de sesión de YouTube, dejar que inicie sesión y luego extraer las cookies del navegador.
La "explotar" en YouTubeExplode proviene del nombre de una función PHP que divide las cadenas, explode(...) . Cuando comenzaba el desarrollo de esta biblioteca, la mayor parte del código fuente de referencia que leí fue escrito en PHP, de ahí la inspiración para el nombre.