Skip to content

插件开发

Harlan edited this page Dec 4, 2022 · 8 revisions

0.简介

目前得插件功能比较完善了,基本可以从最开始没有取到m3u8地址得时候就可以接管处理

  • 插件加载模式
    1. 需要设置dll的名称跟请求下载的m3u8的主机名称一致
    2. 只要plugins中有插件就会自动加载
    3. 如果找到对应主机名称的dll就会采用对应的dll的处理方案进行操作
    4. 每一个下载任务都会new一个新的插件实例

1.创建项目

  1. 创建.net6的类库
  2. 创建项目的时候需要按照格式要求创建dll名称,否则无法加载插件
  3. 名称是M3u8Downloader_H.*.plugin,中间的星号为你需要下载的m3u8的主机名称
  4. 引用M3u8Downloader_H.Plugin.Abstractions.dll
  5. 实现IPluginBuilder接口

2. 实现IPluginBuilder接口

  • 这里的实例是M3u8Downloader_H.bilivideo.plugin这个项目的代码
using M3u8Downloader_H.bilivideo.plugin.Readers;
using M3u8Downloader_H.M3U8.AttributeReaderManager;
using M3u8Downloader_H.Plugin;

namespace M3u8Downloader_H.bilivideo.plugin
{
    public class Class1 : IPluginBuilder
    {
        //这里主要是你可能需要对某些网址直接进行解析可以实现此方案
        //目前插件中已经实现了几个网站得直接解析得功能 可以去github看一下玩法
        public IM3u8UriProvider? CreateM3u8UriProvider() => new LiveClient();

        //此接口是 如果你想实现自己得某种解析m3u8得玩法
        //就可以是实现此接口
        //在插件中vlive.plugin得插件就是实现了此接口来解析一些非m3u8文件得m3u8数据
        public IM3uFileReader? CreateM3u8FileReader() => null;

        //此函数得目的是为了下载得ts可能需要特殊解密
        //这里采用了下面的实现了IDownloadService接口的处理方法
        //这里只要直接返回MyDownloadService的实例即可
        //public IDownloadService? CreatePluginService() => new MyDownloadService();
        
        //此接口是如果你需要对请求得数据网址进行加密和取回得内容解密可以实现此接口
        //在本实例中不需要对请求m3u8的数据等相关内容进行处理,所以直接返回null
        //需要实现此函数的可以看bilivideo插件里的代码
        public IM3u8FileInfoStreamService? CreateM3U8FileInfoStreamService() => null;

        //这里对media这个数据流进行处理 所以采用set函数进行替换原始的处理程序
        //MediaAttributeReader实现了IAttributeReader接口
        //如果你需要对其他个性化的标签进行处理,可以采用Add函数进行添加
        //MediaAttributeReader的具体实现,可以自己看一下代码
        public void SetAttributeReader(IAttributeReaderManager attributeReader)
        {
            attributeReader.Set("#EXTINF", new MediaAttributeReader());
        }
    }
}

3. 实现下载处理接口

1. 对特殊密钥得处理实例

using PluginInterface;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using VideoDownloaderEx.Extensions;

namespace PluginTest3
{
    public class MyDownloadService : IDownloadService
    {
        private byte[] aesKey;
        private byte[] aesIv;

        //此函数会在单线程中调用
        //调用到此函数的时候,会将httpclient,以及header传入
        //那如果你需要发起http请求可以保存这个形参
        public Task Initialize(HttpClient httpClient, IEnumerable<KeyValuePair<string, string>>? headers, M3UFileInfo m3UFileInfo, CancellationToken cancellationToken) => Task.CompletedTask;


        //这个函数是多线程调用得
        public Stream HandleData(Stream stream, CancellationToken cancellationToken)
        {
            //这里的AesDecrypt需要项目引用VideoDownloaderEx.Extensions.dll 然后using VideoDownloaderEx.Extensions即可使用
            return stream.AesDecrypt(aesKey, aesIv);
        }
    }
}

2. 需要发起http请求

using PluginInterface;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using VideoDownloaderEx.Extensions;

namespace PluginTest3
{
    public class  MyDownloadService : IDownloadService
    {
        private byte[] aesKey;

        //这里假设需要是从某地址请求一段密钥
        //如果网站对某些请求头有检测 那请求操作得时候 最好加上请求头
        //此函数会在单线程中调用
        public async Task Initialize(HttpClient httpClient, IEnumerable<KeyValuePair<string, string>>? headers, M3UFileInfo m3UFileInfo, CancellationToken cancellationToken)
        {
            //GetByteArrayAsync 需要项目引用VideoDownloaderEx.Extensions.dll 
            //然后using VideoDownloaderEx.Extensions
            aesKey = await httpClient.GetByteArrayAsync("https://www.xxx.com", headers, cancellationToken);
        }

        //此函数会在多线程中调用
        public Stream HandleData(Stream stream, CancellationToken cancellationToken)
        {
            return stream.AesDecrypt(aesKey, new byte[16]);
        }
    }
}

4. 配置插件文件

  • 只需要.plugin.dll 这一个文件放入即可
  • 将你编写好的插件放入到Plugins目录中,软件在打开的时候会自动加载
  • 如果你需要变更某个插件,或者新加某个插件,请重启软件即可
  • 如果你不想使用某个插件,可以将那个插件移除,或者改名成其他的名字