private static int RunExtractAndReturnExitCode(LaunchOptions.Extract opts) { Quite = opts.Quite; using var flv_stream = File.Open(opts.InputPath, FileMode.Open, FileAccess.Read, FileShare.Read); var tags = FlvReader.ReadFlvFile(flv_stream, opts.TagNum + 1); if (tags.Length > opts.TagNum) { FlvTag tag = tags[opts.TagNum]; if (string.IsNullOrWhiteSpace(opts.OutputPath)) { var s = new MemoryStream(); if (tag.TagType == TagType.Script && !opts.Byte) { FlvWriter.WriteTagData(s, flv_stream, tag); s.Position = 0; var body = ScriptTagBody.Parse(s); Console.WriteLine(body.ToJson()); } else { FlvWriter.WriteTag(s, flv_stream, tag); var str = BitConverter.ToString(s.ToArray()).Replace("-", ""); str = string.Join('\n', str.SplitInParts(64)); Console.WriteLine(str); } return(0); } else { var fi = new FileInfo(opts.OutputPath); if (fi.Exists && !opts.Overwrite) { if (!Quite) { Console.WriteLine("文件已经存在,使用 --force 参数覆盖目标位置文件"); } return(1); } using var output = fi.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.Read); FlvWriter.WriteTag(output, flv_stream, tag); return(0); } } else { if (!Quite) { Console.WriteLine($"文件中只有个 {tags.Length} Tag,而需要第 {opts.TagNum} 个 Tag"); } return(1); } }
private static int RunParseAndReturnExitCode(LaunchOptions.Parse opts) { Quite = opts.Quite; var input = new FileInfo(opts.InputPath); if (!input.Exists) { if (!Quite) { Console.WriteLine("FLV 文件不存在"); } return(1); } var fib = new FileInfo(opts.FibPath); if (fib.Exists && !opts.Overwrite) { if (!Quite) { Console.WriteLine("fib 文件已经存在,使用 --force 参数覆盖目标位置文件"); } return(1); } using var flv_stream = input.Open(FileMode.Open, FileAccess.Read, FileShare.Read); if (!Quite) { Console.WriteLine("读取 FLV 文件中..."); } string hash; if (opts.SkipHash) { hash = string.Empty; } else { using var md5 = MD5.Create(); var bytes = md5.ComputeHash(flv_stream); flv_stream.Position = 0; hash = BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant(); } var tags = FlvReader.ReadFlvFile(flv_stream); if (!Quite) { Console.WriteLine("FLV 文件读取完毕,生成 fib 命令文件..."); } var file = new FlvInteractiveRebaseCommandFile { File = new FlvInteractiveRebaseCommandFile.FlvFile { Hash = hash, SkipHash = opts.SkipHash, Path = input.FullName } }; int index = 0; var memoryStream = new MemoryStream(); file.Tags.AddRange(tags.Select(input_tag => { FlvInteractiveRebaseCommandFile.FlvTag result; if (input_tag.TagType == TagType.Script) { memoryStream.SetLength(0); FlvWriter.WriteTagData(memoryStream, flv_stream, input_tag); memoryStream.Position = 0; var body = ScriptTagBody.Parse(memoryStream); var json = body.ToJson(); result = new FlvInteractiveRebaseCommandFile.FlvTag { Command = FlvInteractiveRebaseCommandFile.FlvTagCommand.Script, Index = index++, TimeStamp = TimeSpan.FromMilliseconds(input_tag.TimeStamp), Value = json, Size = input_tag.TagSize, Offset = input_tag.Position, Type = input_tag.TagType, Header = input_tag.Flag.HasFlag(TagFlag.Header), Keyframe = input_tag.Flag.HasFlag(TagFlag.Keyframe), }; } else { result = new FlvInteractiveRebaseCommandFile.FlvTag { Command = FlvInteractiveRebaseCommandFile.FlvTagCommand.Pick, Index = index++, TimeStamp = TimeSpan.FromMilliseconds(input_tag.TimeStamp), Size = input_tag.TagSize, Offset = input_tag.Position, Type = input_tag.TagType, Header = input_tag.Flag.HasFlag(TagFlag.Header), Keyframe = input_tag.Flag.HasFlag(TagFlag.Keyframe), }; } if (result.Type == TagType.Video && opts.ShowNalu) { var b = new byte[4]; flv_stream.Seek(result.Offset + 11, SeekOrigin.Begin); if ((flv_stream.ReadByte() & 0x0F) == 7 && flv_stream.ReadByte() == 1) { result.Nalus = new List <FlvInteractiveRebaseCommandFile.FlvNalu>(); var end = result.Offset + 11 + result.Size; flv_stream.Seek(3, SeekOrigin.Current); while (true) { if (4 != flv_stream.Read(b)) { break; } var size = BitConverter.ToUInt32(b.ToBE(), 0); var type = flv_stream.ReadByte() & 0b00011111; flv_stream.Seek(size - 1, SeekOrigin.Current); result.Nalus.Add(new FlvInteractiveRebaseCommandFile.FlvNalu { Size = size, Type = type }); if (flv_stream.Position == end) { break; } else if (flv_stream.Position > end) { Console.WriteLine($"Nalu Warning: out of range. Offset: {result.Offset}, Nalu No: {result.Nalus.Count + 1}, Pos: {flv_stream.Position}"); break; } } } } return(result); })); using (var writer = new StreamWriter(fib.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None), new UTF8Encoding(false))) { FlvInteractiveRebaseCommandFile.Serialize(writer, file); } if (!Quite) { Console.WriteLine("成功生成"); } return(0); }