sdcb / Sdcb.FFmpeg

FFmpeg basic .NET API generated by CppSharp
GNU Lesser General Public License v3.0
334 stars 53 forks source link

纯音频例子 #10

Open j4587698 opened 7 months ago

j4587698 commented 7 months ago

能给一个纯音频的转码例子吗? 尝试了一下,总是报错,没有发现网上有类似音频的例子,代码里给的几个例子都有视频流在里面。

感谢周老板

j4587698 commented 7 months ago

我尝试写了一下,

// 打开输入文件
using FormatContext inFc = FormatContext.OpenInputUrl("F:/119127515.mp3");
inFc.LoadStreamInfo();

// 准备输入流/解码器
MediaStream inAudioStream = inFc.GetAudioStream();
using CodecContext audioDecoder = new(Codec.FindDecoderById(inAudioStream.Codecpar!.CodecId));
audioDecoder.FillParameters(inAudioStream.Codecpar);
audioDecoder.Open();
audioDecoder.ChannelLayout = (ulong)ffmpeg.av_get_default_channel_layout(audioDecoder.Channels);

// 设置输出文件
string destFile = "F:/119127515.aac";
using FormatContext outFc = FormatContext.AllocOutput(formatName:"adts");

// 设置输出编码器和流
outFc.AudioCodec = Codec.CommonEncoders.AAC;
MediaStream outAudioStream = outFc.NewStream(outFc.AudioCodec);
using CodecContext audioEncoder = new(outFc.AudioCodec)
{
    Channels = 2,
    SampleFormat = outFc.AudioCodec.Value.NegociateSampleFormat(AVSampleFormat.Fltp),
    SampleRate = outFc.AudioCodec.Value.NegociateSampleRates(48000),
    BitRate = 48000 // 可以根据需要设置比特率
};
audioEncoder.ChannelLayout = (ulong)ffmpeg.av_get_default_channel_layout(audioEncoder.Channels);
audioEncoder.TimeBase = new AVRational(1, audioEncoder.SampleRate);
audioEncoder.Open(outFc.AudioCodec);
outAudioStream.Codecpar!.CopyFrom(audioEncoder);

// 开始写入
using IOContext io = IOContext.OpenWrite(destFile);
outFc.Pb = io;
outFc.WriteHeader();

var decodingQueue = inFc.ReadPackets(inAudioStream.Index).DecodePackets(audioDecoder);

var encoding = decodingQueue.ConvertFrames(audioEncoder).AudioFifo(audioEncoder).EncodeFrames(audioEncoder);

encoding.WriteAll(outFc);
outFc.WriteTrailer();
Console.ReadKey();

这个转码在6.1不好用,会报错。但是在5.1上可以运行,会报警告,并且退出代码也不对。

[mp3float @ 000001a153f18f40] Could not update timestamps for skipped samples.
[mp3float @ 000001a153f18f40] Could not update timestamps for discarded samples.

进程已结束,退出代码为 -1,073,740,940。

但是转出来的aac会有很大的底噪,明显有问题。 能指点一下这个哪里有问题吗?非常感谢

sdcb commented 7 months ago

看了一下,我也没看出来哪里有问题,需要多测测

j4587698 commented 7 months ago

这些过时会有影响吗?

CS0618:属性 'Sdcb.FFmpeg.Codecs.CodecContext.ChannelLayout' 已过时: use ch_layout

CS0618:属性 'Sdcb.FFmpeg.Codecs.CodecContext.Channels' 已过时: use ch_layout.nb_channels

如果用6.1的话会报错

[mp3float @ 000001d882712240] Could not update timestamps for skipped samples.
[aac @ 000001d88239cbc0] Input contains (near) NaN/+-Inf
Unhandled exception. Sdcb.FFmpeg.Common.FFmpegException: [Error sending a frame for encoding]: Invalid argument
   at Sdcb.FFmpeg.Common.FFmpegValidation.ThrowIfError(Int32 errorCode, String message)
   at Sdcb.FFmpeg.Codecs.CodecContext.SendFrame(Frame frame)
   at Sdcb.FFmpeg.Toolboxs.Extensions.CodecContextExtensions.EncodeFrame(CodecContext c, Frame frame, Packet packet, Boolean unref)+MoveNext()
   at Sdcb.FFmpeg.Toolboxs.Extensions.FramesExtensions.EncodeFrames(IEnumerable`1 frames, CodecContext c, Boolean makeSequential)+MoveNext()
   at Sdcb.FFmpeg.Toolboxs.Extensions.PacketsExtensions.WriteAll(IEnumerable`1 packets, FormatContext fc, Boolean unref)
   at Program.<Main>$(String[] args) in D:\dotnet\FfmpegTest\FfmpegTest\Program.cs:line 58
j4587698 commented 7 months ago

119127515.zip 测试用的mp3文件是这个

j4587698 commented 7 months ago

大佬有时间帮忙给看看啊,我想拿它水两篇文章混贡献,现在水不出来啊

SlimeNull commented 2 months ago

说起底噪我就想起来, channel count 为 2, 并且 sample format 为 fltp 或者其他任何 planar 格式的采样格式, 需要填入的采样, 是有 "两个维度的", Frame 的 Data[0] 和 Data[1] 都需要你放入 "frame size" 个数据. 例如你 aac 要求 frame size 为 1024, 那么你需要在 Data[0] 有 1024 个左声道采样数据, 在 Data[1] 有 1024 个右声道采样数据.