Я знаю, что bzier уже правильно ответил на этот вопрос, но я решил упомянуть об этом для будущих читателей:
С парсингом / дешифрованием файлов m3u8 можно обращаться с помощью ffmpeg автоматически.Взглянув на исходный код , мы можем понять, как устанавливается IV, когда он не предоставляется.
Это также задокументировано в RFC 8216.
Если вы чувствуете необходимость сделать это самостоятельно в C #, вот полностью рабочий пример:
string m3u8_url = "https://example.com/file.m3u8";
WebClient web = new WebClient();
Stream m3u8_data = web.OpenRead(m3u8_url);
web.Dispose();
M3u8Content content = new M3u8Content();
M3uPlaylist playlist = content.GetFromStream(m3u8_data);
int media_sequence = 0;
// 16 chars - steal this from the key file.
byte[] key = Encoding.ASCII.GetBytes("0123456701234567");
string path = Path.GetFullPath("output.mp4");
FileStream fs = File.Create(path);
foreach(M3uPlaylistEntry entry in playlist.PlaylistEntries) {
// establish initialization vector
// note: iv must be 16 bytes (AES-128)
byte[] iv = media_sequence.ToBigEndianBytes(); // 8 bytes
iv = new byte[8].Concat(iv).ToArray(); // add 8 empty bytes to beginning
// https://tools.ietf.org/html/rfc8216#section-4.3.2.4
// HLS uses AES-128 w/ CBC & PKCS7
RijndaelManaged algorithm = new RijndaelManaged() {
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = 128,
BlockSize = 128
};
// key = from uri in m3u8 file
// iv = derived from sequence number
algorithm.Key = key;
algorithm.IV = iv;
web = new WebClient();
byte[] data = web.DownloadData(entry.Path);
// create memorystream to store bytes & cryptostream to decrypt
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
// decrypt data to memorystream
cs.Write(data, 0, data.Length);
// write decrypted bytes to our mp4 file
byte[] bytes = ms.ToArray();
fs.Write(bytes, 0, bytes.Length);
// close/dispose those streams
cs.Close();
ms.Close();
cs.Dispose();
ms.Dispose();
// increment media sequence to update initialization vector
media_sequence++;
}
// close the file stream & dispose of it
fs.Close();
fs.Dispose();
Вот функция расширения ToBigEndianBytes, которую я позаимствовал из ответа bzier.
public static byte[] ToBigEndianBytes(this int i) {
byte[] bytes = BitConverter.GetBytes(Convert.ToUInt64(i));
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return bytes;
}
Этот код использует PlaylistsNET для разбора записей плейлиста, и вам придется установить последовательность ключей / начального носителя вручную - но она показывает шифрование и его работу.
Тем не менее, я настоятельно рекомендую использовать ffmpeg.
string cmd = string.Format("ffmpeg -i \"{0}\" -c copy -bsf:a aac_adtstoasc \"{1}\"", m3u8_url, local_mp4_path);
Execute(cmd);
public static void ExecuteCommand(string command) {
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " + command;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
}
Это выполнит то же самое с меньшим количеством кода, и вам не нужно будет конвертировать полученный итоговый файл .ts в .mp4, потому что ffmpeg может сделать это за вас..