[英]Using ffmpeg to convert audio from Red5
我的项目遇到一些问题。
在我的项目中,我需要使用Actionscript实现与RED5服务器的麦克风集成,该脚本用于将音频流存储在服务器上,然后我在Java代码中使用ffmpeg将flv文件转换为mp3。
我在这里面临2个问题:
录制的音频将创建.flv文件,该文件将被缩编。
当我尝试使用ffmpeg将.flv转换为.mp3时,它卡住了,直到我停止Red5服务器。
这是我在两个地方的代码。 请让我知道我在哪里做错了。
录制红色的麦克风音频和流的Actionscipt:
private function initConnection():Void {
trace("Connecting...");
nc = new NetConnection();
nc.client = this;
nc.addEventListener(NetStatusEvent.NET_STATUS, onNetConnectionStatus);
nc.connect("rtmp://127.0.0.1/test");
this.mic = Microphone.getMicrophone();
if (this.mic != null) {
this.mic.rate = 44;
mic.setSilenceLevel(0);
mic.gain = 100;
mic.setUseEchoSuppression(true);
mic.setLoopBack(true);
}
}
要发送Red5:
public function startSending( nc: NetConnection, filename:String ) {
ns = new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS, onNetStreamStatus);
ns.publish(filename, 'record');
ns.attachAudio(mic);
}
要停止录制/发送:
public function stopSending() {
mic.setLoopBack(false);
ns.attachAudio(null);
ns.close();
}
结果.flv存储在服务器上,该文件已被加密。
不将.flv转换为.mp3,我在Java代码中按以下方式使用了ffmpeg:
String ffmpegArgs[] = {executableDir,"-i",flvFile.getAbsolutePath(), "-vn", mp3File.getAbsolutePath()};
Process process = new ProcessBuilder(Arrays.asList(ffmpegArgs)).start();
这将启动文件转换,但是会卡住。 停止服务器一段时间后,它立即显示转换后的文件。 请让我知道,我做错了什么。
我从未使用过Red5,所以在此方面无济于事。 您是在使用服务器存储数据,还是可以将原始字节保存到本地存储(或仅保存在内存中),然后在记录结束后将其发送到Java服务器? 如果是这样,我在项目上解决了类似的问题,该问题用于从ActionScript声音文件(和其他资产)进行视频制作。 如果在发送到服务器之前将字节编码为WAVE,将会有很好的结果。 这里有一个对象可以进行转换-thibault源在这里: https : //code.google.com/p/micrecorder/downloads/detail? name = MicRecorder%201.2.zip & can =2& q =
该软件包中的相关代码是这样的:
public class WavEncoder implements ISoundEncoder
{
private static const RIFF:String = "RIFF";
private static const WAVE:String = "WAVE";
private static const FMT:String = "fmt ";
private static const DATA:String = "data";
private var _bytes:ByteArray = new ByteArray();
private var _buffer:ByteArray = new ByteArray();
private var _volume:Number;
/**
*
* @param volume
*
*/
public function WavEncoder( volume:Number=1 )
{
_volume = volume;
}
/**
*
* @param samples
* @param channels
* @param bits
* @param rate
* @return
*
*/
public function encode( samples:ByteArray, channels:int=2, bits:int=16, rate:int=22100 ):ByteArray
{
//var data:ByteArray = create( samples );
create(samples);
_bytes.length = 0;
_bytes.endian = Endian.LITTLE_ENDIAN;
//create(samples);
_bytes.writeUTFBytes( WavEncoder.RIFF );
//_bytes.writeInt( uint( data.length + 44 ) );
_bytes.writeInt( uint( _buffer.length + 44 ) );
_bytes.writeUTFBytes( WavEncoder.WAVE );
_bytes.writeUTFBytes( WavEncoder.FMT );
_bytes.writeInt( uint( 16 ) );
_bytes.writeShort( uint( 1 ) );
_bytes.writeShort( channels );
_bytes.writeInt( rate );
_bytes.writeInt( uint( rate * channels * ( bits >> 3 ) ) );
_bytes.writeShort( uint( channels * ( bits >> 3 ) ) );
_bytes.writeShort( bits );
_bytes.writeUTFBytes( WavEncoder.DATA );
//_bytes.writeInt( data.length );
_bytes.writeInt(_buffer.length);
//_bytes.writeBytes( data );
_bytes.writeBytes( _buffer);
_bytes.position = 0;
//data.clear();
_buffer.clear();
return _bytes;
}
private function create( bytes:ByteArray ):ByteArray {
if(!_buffer)
_buffer = new ByteArray();
_buffer.endian = Endian.LITTLE_ENDIAN;
_buffer.length = 0;
bytes.position = 0;
while( bytes.bytesAvailable )
_buffer.writeShort( bytes.readFloat() * (0x7fff * _volume) );
return _buffer;
}
}
FFmpeg可能无法理解您的编码,因此正在尝试但失败了。 不确定我发布的内容是否对您有帮助,但我以防万一。 让我知道您是否对如何完全实现此功能以使用FFmpeg,Java和AS获得与您尝试执行的操作类似的声音有疑问。
终于我得到了答案。
场景是这样的:
由于我的.flv源文件已损坏,因此当我从命令行执行ffmpeg命令时,它会显示许多警告。
当我从Java代码执行相同的命令时,警告会在jvm中缓冲,因此警告已满,进程挂起。 我在另一个stackoverflow线程中找到了解决方案,我们需要通过读取流来清除错误和其他信息。 这是该代码;
final BufferedReader stderr = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = "";
for (l = 0; ((line = stderr.readLine()) != null);) {
System.out.println(line)
l++;
}
stderr.close();
它为我工作!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.