
Recherche avancée
Médias (1)
-
Bug de détection d’ogg
22 mars 2013, par
Mis à jour : Avril 2013
Langue : français
Type : Video
Autres articles (72)
-
Des sites réalisés avec MediaSPIP
2 mai 2011, parCette page présente quelques-uns des sites fonctionnant sous MediaSPIP.
Vous pouvez bien entendu ajouter le votre grâce au formulaire en bas de page. -
Support audio et vidéo HTML5
10 avril 2011MediaSPIP utilise les balises HTML5 video et audio pour la lecture de documents multimedia en profitant des dernières innovations du W3C supportées par les navigateurs modernes.
Pour les navigateurs plus anciens, le lecteur flash Flowplayer est utilisé.
Le lecteur HTML5 utilisé a été spécifiquement créé pour MediaSPIP : il est complètement modifiable graphiquement pour correspondre à un thème choisi.
Ces technologies permettent de distribuer vidéo et son à la fois sur des ordinateurs conventionnels (...) -
HTML5 audio and video support
13 avril 2011, parMediaSPIP uses HTML5 video and audio tags to play multimedia files, taking advantage of the latest W3C innovations supported by modern browsers.
The MediaSPIP player used has been created specifically for MediaSPIP and can be easily adapted to fit in with a specific theme.
For older browsers the Flowplayer flash fallback is used.
MediaSPIP allows for media playback on major mobile platforms with the above (...)
Sur d’autres sites (7928)
-
Decoding and playing audio with ffmpeg and XAudio2 - frequency ratio wrong
9 mars, par Brent de CarteretI'm using
ffmpeg
to decode audio and output it using the XAudio2 API, it works and plays synced with the video output using the pts. But it's high pitched (i.e. sounds like chipmunks).

Setting breakpoints I can see it has set the correct sample rate from the audio codec in CreateSourceVoice. I'm stumped.


Any help would be much appreciated.


CDVDAUDIO.cpp


#include "DVDAudioDevice.h"
 
HANDLE m_hBufferEndEvent;

CDVDAudio::CDVDAudio()
{
 m_pXAudio2 = NULL;
 m_pMasteringVoice = NULL;
 m_pSourceVoice = NULL;
 m_pWfx = NULL;
 m_VoiceCallback = NULL; 
 m_hBufferEndEvent = CreateEvent(NULL, false, false, "Buffer end event");
}
 
CDVDAudio::~CDVDAudio()
{
 m_pXAudio2 = NULL;
 m_pMasteringVoice = NULL;
 m_pSourceVoice = NULL;
 m_pWfx = NULL;
 m_VoiceCallback = NULL;
 CloseHandle(m_hBufferEndEvent);
 m_hBufferEndEvent = NULL;
}
 
bool CDVDAudio::Create(int iChannels, int iBitrate, int iBitsPerSample, bool bPasstrough)
{
 CoInitializeEx(NULL, COINIT_MULTITHREADED);
 HRESULT hr = XAudio2Create( &m_pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
 
 if (SUCCEEDED(hr))
 {
 m_pXAudio2->CreateMasteringVoice( &m_pMasteringVoice );
 }
 
 // Create source voice
 WAVEFORMATEXTENSIBLE wfx;
 memset(&wfx, 0, sizeof(WAVEFORMATEXTENSIBLE));
 
 wfx.Format.wFormatTag = WAVE_FORMAT_PCM;
 wfx.Format.nSamplesPerSec = iBitrate;//pFFMpegData->pAudioCodecCtx->sample_rate;//48000 by default
 wfx.Format.nChannels = iChannels;//pFFMpegData->pAudioCodecCtx->channels;
 wfx.Format.wBitsPerSample = 16;
 wfx.Format.nBlockAlign = wfx.Format.nChannels*16/8;
 wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
 wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
 wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample;
 
 if(wfx.Format.nChannels == 1)
 {
 wfx.dwChannelMask = SPEAKER_MONO;
 }
 else if(wfx.Format.nChannels == 2)
 {
 wfx.dwChannelMask = SPEAKER_STEREO;
 }
 else if(wfx.Format.nChannels == 5)
 {
 wfx.dwChannelMask = SPEAKER_5POINT1;
 }
 
 wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
 
 unsigned int flags = 0;//XAUDIO2_VOICE_NOSRC;// | XAUDIO2_VOICE_NOPITCH;
 
 //Source voice
 m_VoiceCallback = new StreamingVoiceCallback(this);
 hr = m_pXAudio2->CreateSourceVoice(&m_pSourceVoice,(WAVEFORMATEX*)&wfx, 0 , 1.0f, m_VoiceCallback);
 
 if (!SUCCEEDED(hr))
 return false;
 
 // Start sound
 hr = m_pSourceVoice->Start(0);
 
 if(!SUCCEEDED(hr))
 return false;
 
 return true;
}
 
DWORD CDVDAudio::AddPackets(unsigned char* data, DWORD len)
{ 
 memset(&m_SoundBuffer,0,sizeof(XAUDIO2_BUFFER));
 m_SoundBuffer.AudioBytes = len;
 m_SoundBuffer.pAudioData = data;
 m_SoundBuffer.pContext = NULL;//(VOID*)data;
 XAUDIO2_VOICE_STATE state;
 
 while (m_pSourceVoice->GetState( &state ), state.BuffersQueued > 60)
 {
 WaitForSingleObject( m_hBufferEndEvent, INFINITE );
 }
 
 m_pSourceVoice->SubmitSourceBuffer( &m_SoundBuffer );
 return 0;
}
 
void CDVDAudio::Destroy()
{
 m_pMasteringVoice->DestroyVoice();
 m_pXAudio2->Release();
 m_pSourceVoice->DestroyVoice();
 delete m_VoiceCallback;
 m_VoiceCallback = NULL;
}



CDVDAUdioCodecFFmpeg.cpp


#include "DVDAudioCodecFFmpeg.h"
#include "Log.h"
 
CDVDAudioCodecFFmpeg::CDVDAudioCodecFFmpeg() : CDVDAudioCodec()
{
 m_iBufferSize = 0;
 m_pCodecContext = NULL;
 m_bOpenedCodec = false;
}
 
CDVDAudioCodecFFmpeg::~CDVDAudioCodecFFmpeg()
{
 Dispose();
}
 
bool CDVDAudioCodecFFmpeg::Open(AVCodecID codecID, int iChannels, int iSampleRate)
{
 AVCodec* pCodec;
 m_bOpenedCodec = false;
 av_register_all();
 pCodec = avcodec_find_decoder(codecID);
 m_pCodecContext = avcodec_alloc_context3(pCodec);//avcodec_alloc_context();
 avcodec_get_context_defaults3(m_pCodecContext, pCodec);
 
 if (!pCodec)
 {
 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to find codec");
 return false;
 }
 
 m_pCodecContext->debug_mv = 0;
 m_pCodecContext->debug = 0;
 m_pCodecContext->workaround_bugs = 1;
 
 if (pCodec->capabilities & CODEC_CAP_TRUNCATED)
 m_pCodecContext->flags |= CODEC_FLAG_TRUNCATED;
 
 m_pCodecContext->channels = iChannels;
 m_pCodecContext->sample_rate = iSampleRate;
 //m_pCodecContext->bits_per_sample = 24;
 
 /* //FIXME BRENT
 if( ExtraData && ExtraSize > 0 )
 {
 m_pCodecContext->extradata_size = ExtraSize;
 m_pCodecContext->extradata = m_dllAvCodec.av_mallocz(ExtraSize + FF_INPUT_BUFFER_PADDING_SIZE);
 memcpy(m_pCodecContext->extradata, ExtraData, ExtraSize);
 }
 */
 
 // set acceleration
 //m_pCodecContext->dsp_mask = FF_MM_FORCE | FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE; //BRENT
 
 if (avcodec_open2(m_pCodecContext, pCodec, NULL) < 0)
 {
 CLog::Log(LOGERROR, "CDVDAudioCodecFFmpeg::Open() Unable to open codec");
 Dispose();
 return false;
 }
 
 m_bOpenedCodec = true;
 return true;
}
 
void CDVDAudioCodecFFmpeg::Dispose()
{
 if (m_pCodecContext)
 {
 if (m_bOpenedCodec)
 avcodec_close(m_pCodecContext);
 m_bOpenedCodec = false;
 av_free(m_pCodecContext);
 m_pCodecContext = NULL;
 }
 m_iBufferSize = 0;
}

int CDVDAudioCodecFFmpeg::Decode(BYTE* pData, int iSize)
{
 int iBytesUsed;
 if (!m_pCodecContext) return -1;
 
 //Copy into a FFMpeg AVPAcket again
 AVPacket packet;
 av_init_packet(&packet);
 
 packet.data=pData;
 packet.size=iSize;
 
 int iOutputSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; //BRENT
 
 iBytesUsed = avcodec_decode_audio3(m_pCodecContext, (int16_t *)m_buffer, &iOutputSize/*m_iBufferSize*/, &packet);

 m_iBufferSize = iOutputSize;//BRENT

 return iBytesUsed;
}

int CDVDAudioCodecFFmpeg::GetData(BYTE** dst)
{
 *dst = m_buffer;
 return m_iBufferSize;
}

void CDVDAudioCodecFFmpeg::Reset()
{
 if (m_pCodecContext)
 avcodec_flush_buffers(m_pCodecContext);
}

int CDVDAudioCodecFFmpeg::GetChannels()
{
 if (m_pCodecContext)
 return m_pCodecContext->channels;
 return 0;
}

int CDVDAudioCodecFFmpeg::GetSampleRate()
{
 if (m_pCodecContext)
 return m_pCodecContext->sample_rate;
 return 0;
}
 
int CDVDAudioCodecFFmpeg::GetBitsPerSample()
{
 if (m_pCodecContext)
 return 16;
 return 0;
}



CDVDPlayerAudio.cpp


#include "DVDPlayerAudio.h"
#include "DVDDemuxUtils.h"
#include "Log.h"
 
#include 
#include "DVDAudioCodecFFmpeg.h" //FIXME Move to a codec factory!!
 
CDVDPlayerAudio::CDVDPlayerAudio(CDVDClock* pClock) : CThread()
{
 m_pClock = pClock;
 m_pAudioCodec = NULL;
 m_bInitializedOutputDevice = false;
 m_iSourceChannels = 0;
 m_audioClock = 0;
 
 // m_currentPTSItem.pts = DVD_NOPTS_VALUE;
 // m_currentPTSItem.timestamp = 0;
 
 SetSpeed(DVD_PLAYSPEED_NORMAL);
 
 InitializeCriticalSection(&m_critCodecSection);
 m_messageQueue.SetMaxDataSize(10 * 16 * 1024);
 // g_dvdPerformanceCounter.EnableAudioQueue(&m_packetQueue);
}

CDVDPlayerAudio::~CDVDPlayerAudio()
{
 // g_dvdPerformanceCounter.DisableAudioQueue();

 // close the stream, and don't wait for the audio to be finished
 CloseStream(true);
 DeleteCriticalSection(&m_critCodecSection);
}

bool CDVDPlayerAudio::OpenStream( CDemuxStreamAudio *pDemuxStream )
{
 // should always be NULL!!!!, it will probably crash anyway when deleting m_pAudioCodec here.
 if (m_pAudioCodec)
 {
 CLog::Log(LOGFATAL, "CDVDPlayerAudio::OpenStream() m_pAudioCodec != NULL");
 return false;
 }
 
 AVCodecID codecID = pDemuxStream->codec;
 
 CLog::Log(LOGNOTICE, "Finding audio codec for: %i", codecID);
 //m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec( pDemuxStream ); 
 m_pAudioCodec = new CDVDAudioCodecFFmpeg; //FIXME BRENT Codec Factory needed!
 
 if (!m_pAudioCodec->Open(pDemuxStream->codec, pDemuxStream->iChannels, pDemuxStream->iSampleRate))
 {
 m_pAudioCodec->Dispose();
 delete m_pAudioCodec;
 m_pAudioCodec = NULL;
 return false;
 }
 
 if ( !m_pAudioCodec )
 {
 CLog::Log(LOGERROR, "Unsupported audio codec");
 return false;
 }
 
 m_codec = pDemuxStream->codec;
 m_iSourceChannels = pDemuxStream->iChannels;
 m_messageQueue.Init();
 
 CLog::Log(LOGNOTICE, "Creating audio thread");
 Create();
 
 return true;
}

void CDVDPlayerAudio::CloseStream(bool bWaitForBuffers)
{
 // wait until buffers are empty
 if (bWaitForBuffers)
 m_messageQueue.WaitUntilEmpty();
 
 // send abort message to the audio queue
 m_messageQueue.Abort();
 
 CLog::Log(LOGNOTICE, "waiting for audio thread to exit");
 
 // shut down the audio_decode thread and wait for it
 StopThread(); // will set this->m_bStop to true
 this->WaitForThreadExit(INFINITE);
 
 // uninit queue
 m_messageQueue.End();
 
 CLog::Log(LOGNOTICE, "Deleting audio codec");
 if (m_pAudioCodec)
 {
 m_pAudioCodec->Dispose();
 delete m_pAudioCodec;
 m_pAudioCodec = NULL;
 }
 
 // flush any remaining pts values
 //FlushPTSQueue(); //FIXME BRENT
}

void CDVDPlayerAudio::OnStartup()
{
 CThread::SetName("CDVDPlayerAudio");
 pAudioPacket = NULL;
 m_audioClock = 0;
 audio_pkt_data = NULL;
 audio_pkt_size = 0;
 
 // g_dvdPerformanceCounter.EnableAudioDecodePerformance(ThreadHandle());
}

void CDVDPlayerAudio::Process()
{
 CLog::Log(LOGNOTICE, "running thread: CDVDPlayerAudio::Process()");

 int result;
 
 // silence data
 BYTE silence[1024];
 memset(silence, 0, 1024);
 
 DVDAudioFrame audioframe;
 
 __int64 iClockDiff=0;
 while (!m_bStop)
 {
 //Don't let anybody mess with our global variables
 EnterCriticalSection(&m_critCodecSection);
 result = DecodeFrame(audioframe, m_speed != DVD_PLAYSPEED_NORMAL); // blocks if no audio is available, but leaves critical section before doing so
 LeaveCriticalSection(&m_critCodecSection);
 
 if ( result & DECODE_FLAG_ERROR ) 
 { 
 CLog::Log(LOGERROR, "CDVDPlayerAudio::Process - Decode Error. Skipping audio frame");
 continue;
 }
 
 if ( result & DECODE_FLAG_ABORT )
 {
 CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Abort received, exiting thread");
 break;
 }
 
 if ( result & DECODE_FLAG_DROP ) //FIXME BRENT
 {
 /* //frame should be dropped. Don't let audio move ahead of the current time thou
 //we need to be able to start playing at any time
 //when playing backwards, we try to keep as small buffers as possible
 
 // set the time at this delay
 AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay());
 */
 if (m_speed > 0)
 {
 __int64 timestamp = m_pClock->GetAbsoluteClock() + (audioframe.duration * DVD_PLAYSPEED_NORMAL) / m_speed;
 while ( !m_bStop && timestamp > m_pClock->GetAbsoluteClock() )
 Sleep(1);
 }
 continue;
 }
 
 if ( audioframe.size > 0 ) 
 {
 // we have successfully decoded an audio frame, open up the audio device if not already done
 if (!m_bInitializedOutputDevice)
 {
 m_bInitializedOutputDevice = InitializeOutputDevice();
 }
 
 //Add any packets play
 m_dvdAudio.AddPackets(audioframe.data, audioframe.size);
 
 // store the delay for this pts value so we can calculate the current playing
 //AddPTSQueue(audioframe.pts, m_dvdAudio.GetDelay() - audioframe.duration);//BRENT
 }
 
 // if we where asked to resync on this packet, do so here
 if ( result & DECODE_FLAG_RESYNC )
 {
 CLog::Log(LOGDEBUG, "CDVDPlayerAudio::Process - Resync recieved.");
 //while (!m_bStop && (unsigned int)m_dvdAudio.GetDelay() > audioframe.duration ) Sleep(5); //BRENT
 m_pClock->Discontinuity(CLOCK_DISC_NORMAL, audioframe.pts);
 }
 
 #ifdef USEOLDSYNC
 //Clock should be calculated after packets have been added as m_audioClock points to the 
 //time after they have been played
 
 const __int64 iCurrDiff = (m_audioClock - m_dvdAudio.GetDelay()) - m_pClock->GetClock();
 const __int64 iAvDiff = (iClockDiff + iCurrDiff)/2;
 
 //Check for discontinuity in the stream, use a moving average to
 //eliminate highfreq fluctuations of large packet sizes
 if ( ABS(iAvDiff) > 5000 ) // sync clock if average diff is bigger than 5 msec 
 {
 //Wait until only the new audio frame which triggered the discontinuity is left
 //then set disc state
 while (!m_bStop && (unsigned int)m_dvdAudio.GetBytesInBuffer() > audioframe.size )
 Sleep(5);
 
 m_pClock->Discontinuity(CLOCK_DISC_NORMAL, m_audioClock - m_dvdAudio.GetDelay());
 CLog::("CDVDPlayer:: Detected Audio Discontinuity, syncing clock. diff was: %I64d, %I64d, av: %I64d", iClockDiff, iCurrDiff, iAvDiff);
 iClockDiff = 0;
 }
 else
 {
 //Do gradual adjustments (not working yet)
 //m_pClock->AdjustSpeedToMatch(iClock + iAvDiff);
 iClockDiff = iCurrDiff;
 }
 #endif
 }
}

void CDVDPlayerAudio::OnExit()
{
 //g_dvdPerformanceCounter.DisableAudioDecodePerformance();
 
 // destroy audio device
 CLog::Log(LOGNOTICE, "Closing audio device");
 m_dvdAudio.Destroy();
 m_bInitializedOutputDevice = false;

 CLog::Log(LOGNOTICE, "thread end: CDVDPlayerAudio::OnExit()");
}

// decode one audio frame and returns its uncompressed size
int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket)
{
 CDVDDemux::DemuxPacket* pPacket = pAudioPacket;
 int n=48000*2*16/8, len;
 
 //Store amount left at this point, and what last pts was
 unsigned __int64 first_pkt_pts = 0;
 int first_pkt_size = 0; 
 int first_pkt_used = 0;
 int result = 0;
 
 // make sure the sent frame is clean
 memset(&audioframe, 0, sizeof(DVDAudioFrame));
 
 if (pPacket)
 {
 first_pkt_pts = pPacket->pts;
 first_pkt_size = pPacket->iSize;
 first_pkt_used = first_pkt_size - audio_pkt_size;
 }
 
 for (;;)
 {
 /* NOTE: the audio packet can contain several frames */
 while (audio_pkt_size > 0)
 {
 len = m_pAudioCodec->Decode(audio_pkt_data, audio_pkt_size);
 if (len < 0)
 {
 /* if error, we skip the frame */
 audio_pkt_size=0;
 m_pAudioCodec->Reset();
 break;
 }
 
 // fix for fucked up decoders //FIXME BRENT
 if( len > audio_pkt_size )
 { 
 CLog::Log(LOGERROR, "CDVDPlayerAudio:DecodeFrame - Codec tried to consume more data than available. Potential memory corruption"); 
 audio_pkt_size=0;
 m_pAudioCodec->Reset();
 assert(0);
 }
 
 // get decoded data and the size of it
 audioframe.size = m_pAudioCodec->GetData(&audioframe.data);
 audio_pkt_data += len;
 audio_pkt_size -= len;
 
 if (audioframe.size <= 0)
 continue;
 
 audioframe.pts = m_audioClock;
 
 // compute duration.
 n = m_pAudioCodec->GetChannels() * m_pAudioCodec->GetBitsPerSample() / 8 * m_pAudioCodec->GetSampleRate();
 if (n > 0)
 {
 // safety check, if channels == 0, n will result in 0, and that will result in a nice divide exception
 audioframe.duration = (unsigned int)(((__int64)audioframe.size * DVD_TIME_BASE) / n);
 
 // increase audioclock to after the packet
 m_audioClock += audioframe.duration;
 }
 
 //If we are asked to drop this packet, return a size of zero. then it won't be played
 //we currently still decode the audio.. this is needed since we still need to know it's 
 //duration to make sure clock is updated correctly.
 if ( bDropPacket )
 {
 result |= DECODE_FLAG_DROP;
 }
 return result;
 }
 
 // free the current packet
 if (pPacket)
 {
 CDVDDemuxUtils::FreeDemuxPacket(pPacket); //BRENT FIXME
 pPacket = NULL;
 pAudioPacket = NULL;
 }
 
 if (m_messageQueue.RecievedAbortRequest())
 return DECODE_FLAG_ABORT;
 
 // read next packet and return -1 on error
 LeaveCriticalSection(&m_critCodecSection); //Leave here as this might stall a while
 
 CDVDMsg* pMsg;
 MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, INFINITE);
 EnterCriticalSection(&m_critCodecSection);
 
 if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT)
 return DECODE_FLAG_ABORT;
 
 if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
 {
 CDVDMsgDemuxerPacket* pMsgDemuxerPacket = (CDVDMsgDemuxerPacket*)pMsg;
 pPacket = pMsgDemuxerPacket->GetPacket();
 pMsgDemuxerPacket->m_pPacket = NULL; // XXX, test
 pAudioPacket = pPacket;
 audio_pkt_data = pPacket->pData;
 audio_pkt_size = pPacket->iSize;
 }
 else
 {
 // other data is not used here, free if
 // msg itself will still be available
 pMsg->Release();
 }
 
 // if update the audio clock with the pts
 if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET) || pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
 {
 if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC))
 { 
 //player asked us to sync on this package
 CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg;
 result |= DECODE_FLAG_RESYNC;
 m_audioClock = pMsgGeneralResync->GetPts();
 }
 else if (pPacket->pts != DVD_NOPTS_VALUE) // CDVDMsg::DEMUXER_PACKET, pPacket is already set above
 {
 if (first_pkt_size == 0) 
 { 
 //first package
 m_audioClock = pPacket->pts; 
 }
 else if (first_pkt_pts > pPacket->pts)
 { 
 //okey first packet in this continous stream, make sure we use the time here 
 m_audioClock = pPacket->pts; 
 }
 else if ((unsigned __int64)m_audioClock < pPacket->pts || (unsigned __int64)m_audioClock > pPacket->pts)
 {
 //crap, moved outsided correct pts
 //Use pts from current packet, untill we find a better value for it.
 //Should be ok after a couple of frames, as soon as it starts clean on a packet
 m_audioClock = pPacket->pts;
 }
 else if (first_pkt_size == first_pkt_used)
 {
 //Nice starting up freshly on the start of a packet, use pts from it
 m_audioClock = pPacket->pts;
 }
 }
 }
 pMsg->Release();
 }
}

void CDVDPlayerAudio::SetSpeed(int speed)
{ 
 m_speed = speed;
 
 //if (m_speed == DVD_PLAYSPEED_PAUSE) m_dvdAudio.Pause(); //BRENT FIXME
 //else m_dvdAudio.Resume();
}
 
bool CDVDPlayerAudio::InitializeOutputDevice()
{
 int iChannels = m_pAudioCodec->GetChannels();
 int iSampleRate = m_pAudioCodec->GetSampleRate();
 int iBitsPerSample = m_pAudioCodec->GetBitsPerSample();
 //bool bPasstrough = m_pAudioCodec->NeedPasstrough(); //BRENT
 
 if (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)
 {
 CLog::Log(LOGERROR, "Unable to create audio device, (iChannels == 0 || iSampleRate == 0 || iBitsPerSample == 0)");
 return false;
 }
 
 CLog::Log(LOGNOTICE, "Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);
 if (m_dvdAudio.Create(iChannels, iSampleRate, iBitsPerSample, /*bPasstrough*/0)) // always 16 bit with ffmpeg ? //BRENT Passthrough needed?
 {
 return true;
 }
 
 CLog::Log(LOGERROR, "Failed Creating audio device with codec id: %i, channels: %i, sample rate: %i", m_codec, iChannels, iSampleRate);
 return false;
}



-
ffmpeg Audiosegment error in get audio chunks in socketIo server in python
26 janvier 2024, par a_crszkvc30Last_NameColI want to send each audio chunk every minute.
this is the test code and i want to save audiofile and audio chunk file.
then, i will combine two audio files stop button was worked correctly but with set time function is not worked in python server.
there is python server code with socketio


def handle_voice(sid,data): # blob 으로 들어온 데이터 
 # BytesIO를 사용하여 메모리 상에서 오디오 데이터를 로드
 audio_segment = AudioSegment.from_file(BytesIO(data), format="webm")
 directory = "dddd"
 # 오디오 파일로 저장
 #directory = str(names_sid.get(sid))
 if not os.path.exists(directory):
 os.makedirs(directory)
 
 # 오디오 파일로 저장
 file_path = os.path.join(directory, f'{sid}.wav')
 audio_segment.export(file_path, format='wav') 
 print('오디오 파일 저장 완료')`
 



and there is client






 
 
 <code class="echappe-js"><script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.2/socket.io.js"></script>




 






<script>&#xA; var socket = io(&#x27;http://127.0.0.1:5000&#x27;);&#xA; const record = document.getElementById("record")&#xA; const stop = document.getElementById("stop")&#xA; const soundClips = document.getElementById("sound-clips")&#xA; const chkHearMic = document.getElementById("chk-hear-mic")&#xA;&#xA; const audioCtx = new(window.AudioContext || window.webkitAudioContext)() // 오디오 컨텍스트 정의&#xA;&#xA; const analyser = audioCtx.createAnalyser()&#xA; // const distortion = audioCtx.createWaveShaper()&#xA; // const gainNode = audioCtx.createGain()&#xA; // const biquadFilter = audioCtx.createBiquadFilter()&#xA;&#xA; function makeSound(stream) {&#xA; const source = audioCtx.createMediaStreamSource(stream)&#xA; socket.connect()&#xA; source.connect(analyser)&#xA; // analyser.connect(distortion)&#xA; // distortion.connect(biquadFilter)&#xA; // biquadFilter.connect(gainNode)&#xA; // gainNode.connect(audioCtx.destination) // connecting the different audio graph nodes together&#xA; analyser.connect(audioCtx.destination)&#xA;&#xA; }&#xA;&#xA; if (navigator.mediaDevices) {&#xA; console.log(&#x27;getUserMedia supported.&#x27;)&#xA;&#xA; const constraints = {&#xA; audio: true&#xA; }&#xA; let chunks = []&#xA;&#xA; navigator.mediaDevices.getUserMedia(constraints)&#xA; .then(stream => {&#xA;&#xA; const mediaRecorder = new MediaRecorder(stream)&#xA; &#xA; chkHearMic.onchange = e => {&#xA; if(e.target.checked == true) {&#xA; audioCtx.resume()&#xA; makeSound(stream)&#xA; } else {&#xA; audioCtx.suspend()&#xA; }&#xA; }&#xA; &#xA; record.onclick = () => {&#xA; mediaRecorder.start(1000)&#xA; console.log(mediaRecorder.state)&#xA; console.log("recorder started")&#xA; record.style.background = "red"&#xA; record.style.color = "black"&#xA; }&#xA;&#xA; stop.onclick = () => {&#xA; mediaRecorder.stop()&#xA; console.log(mediaRecorder.state)&#xA; console.log("recorder stopped")&#xA; record.style.background = ""&#xA; record.style.color = ""&#xA; }&#xA;&#xA; mediaRecorder.onstop = e => {&#xA; console.log("data available after MediaRecorder.stop() called.")&#xA; const bb = new Blob(chunks, { &#x27;type&#x27; : &#x27;audio/wav&#x27; })&#xA; socket.emit(&#x27;voice&#x27;,bb)&#xA; const clipName = prompt("오디오 파일 제목을 입력하세요.", new Date())&#xA;&#xA; const clipContainer = document.createElement(&#x27;article&#x27;)&#xA; const clipLabel = document.createElement(&#x27;p&#x27;)&#xA; const audio = document.createElement(&#x27;audio&#x27;)&#xA; const deleteButton = document.createElement(&#x27;button&#x27;)&#xA;&#xA; clipContainer.classList.add(&#x27;clip&#x27;)&#xA; audio.setAttribute(&#x27;controls&#x27;, &#x27;&#x27;)&#xA; deleteButton.innerHTML = "삭제"&#xA; clipLabel.innerHTML = clipName&#xA;&#xA; clipContainer.appendChild(audio)&#xA; clipContainer.appendChild(clipLabel)&#xA; clipContainer.appendChild(deleteButton)&#xA; soundClips.appendChild(clipContainer)&#xA;&#xA; audio.controls = true&#xA; const blob = new Blob(chunks, {&#xA; &#x27;type&#x27;: &#x27;audio/ogg codecs=opus&#x27;&#xA; })&#xA;&#xA; chunks = []&#xA; const audioURL = URL.createObjectURL(blob)&#xA; audio.src = audioURL&#xA; console.log("recorder stopped")&#xA;&#xA; deleteButton.onclick = e => {&#xA; evtTgt = e.target&#xA; evtTgt .parentNode.parentNode.removeChild(evtTgt.parentNode)&#xA; }&#xA; }&#xA;&#xA; mediaRecorder.ondataavailable = function(e) {&#xA; chunks.push(e.data)&#xA; if (chunks.length >= 5)&#xA; {&#xA; const bloddb = new Blob(chunks, { &#x27;type&#x27; : &#x27;audio/wav&#x27; })&#xA; socket.emit(&#x27;voice&#x27;, bloddb)&#xA; &#xA; chunks = []&#xA; }&#xA; mediaRecorder.sendData = function(buffer) {&#xA; const bloddb = new Blob(buffer, { &#x27;type&#x27; : &#x27;audio/wav&#x27; })&#xA; socket.emit(&#x27;voice&#x27;, bloddb)&#xA;}&#xA;};&#xA; })&#xA; .catch(err => {&#xA; console.log(&#x27;The following error occurred: &#x27; &#x2B; err)&#xA; })&#xA; }&#xA; </script>




ask exception was never retrieved
future: <task finished="finished" coro="<InstrumentedAsyncServer._handle_event_internal()" defined="defined" at="at"> exception=CouldntDecodeError('Decoding failed. ffmpeg returned error code: 3199971767\n\nOutput from ffmpeg/avlib:\n\nffmpeg version 6.1.1-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers\r\n built with gcc 12.2.0 (Rev10, Built by MSYS2 project)\r\n configuration: --enable-gpl --enable-version3 --enable-static --pkg-config=pkgconf --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-dxva2 --enable-d3d11va --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint\r\n libavutil 58. 29.100 / 58. 29.100\r\n libavcodec 60. 31.102 / 60. 31.102\r\n libavformat 60. 16.100 / 60. 16.100\r\n libavdevice 60. 3.100 / 60. 3.100\r\n libavfilter 9. 12.100 / 9. 12.100\r\n libswscale 7. 5.100 / 7. 5.100\r\n libswresample 4. 12.100 / 4. 12.100\r\n libpostproc 57. 3.100 / 57. 3.100\r\n[cache @ 000001d9828efe40] Inner protocol failed to seekback end : -40\r\n[matroska,webm @ 000001d9828efa00] EBML header parsing failed\r\n[cache @ 000001d9828efe40] Statistics, cache hits:0 cache misses:3\r\n[in#0 @ 000001d9828da3c0] Error opening input: Invalid data found when processing input\r\nError opening input file cache:pipe:0.\r\nError opening input files: Invalid data found when processing input\r\n')>
Traceback (most recent call last):
 File "f:\fastapi-socketio-wb38\.vent\Lib\site-packages\socketio\async_admin.py", line 276, in _handle_event_internal
 ret = await self.sio.__handle_event_internal(server, sid, eio_sid,
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "f:\fastapi-socketio-wb38\.vent\Lib\site-packages\socketio\async_server.py", line 597, in _handle_event_internal
 r = await server._trigger_event(data[0], namespace, sid, *data[1:])
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "f:\fastapi-socketio-wb38\.vent\Lib\site-packages\socketio\async_server.py", line 635, in _trigger_event
 ret = handler(*args)
 ^^^^^^^^^^^^^^
 File "f:\fastapi-socketio-wb38\Python-Javascript-Websocket-Video-Streaming--main\poom2.py", line 153, in handle_voice
 audio_segment = AudioSegment.from_file(BytesIO(data), format="webm")
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "f:\fastapi-socketio-wb38\.vent\Lib\site-packages\pydub\audio_segment.py", line 773, in from_file
 raise CouldntDecodeError(
pydub.exceptions.CouldntDecodeError: Decoding failed. ffmpeg returned error code: 3199971767

Output from ffmpeg/avlib:

ffmpeg version 6.1.1-full_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developers
 built with gcc 12.2.0 (Rev10, Built by MSYS2 project)
 configuration: --enable-gpl --enable-version3 --enable-static --pkg-config=pkgconf --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-ffnvcodec --enable-nvdec --enable-nvenc --enable-dxva2 --enable-d3d11va --enable-libvpl --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprint
 libavutil 58. 29.100 / 58. 29.100
 libavcodec 60. 31.102 / 60. 31.102
 libavformat 60. 16.100 / 60. 16.100
 libavdevice 60. 3.100 / 60. 3.100
 libavfilter 9. 12.100 / 9. 12.100
 libswscale 7. 5.100 / 7. 5.100
 libswresample 4. 12.100 / 4. 12.100
 libpostproc 57. 3.100 / 57. 3.100
[cache @ 000001d9828efe40] Inner protocol failed to seekback end : -40
[matroska,webm @ 000001d9828efa00] EBML header parsing failed
[cache @ 000001d9828efe40] Statistics, cache hits:0 cache misses:3
[in#0 @ 000001d9828da3c0] Error opening input: Invalid data found when processing input
Error opening input file cache:pipe:0.
Error opening input files: Invalid data found when processing input
</task>


im using version of ffmpeg-6.1.1-full_build.
i dont know this error exist the stop button sent event correctly. but chunk data was not work correctly in python server.
my english was so bad. sry


-
How to stop ffmpeg when there's no incoming rtmp stream
5 juillet 2016, par M. IrichI use ffmpeg together with nginx-rtmp.
The thing is ffmpeg doesn’t finish the process when the stream’s finishedI use the following command :
ffmpeg -i 'rtmp://localhost:443/live/test' -loglevel debug -c:a libfdk_aac -b:a 192k -c:v libx264 -profile baseline -preset superfast -tune zerolatency -b:v 2500k -maxrate 4500k -minrate 1500k -bufsize 9000k -keyint_min 15 -g 15 -f dash -use_timeline 1 -use_template 1 -min_seg_duration 5000 -y /tmp/dash/test/test.mpd
but even the stream’s not running ffmpeg still can’t finish the process and is waiting for the rtmp stream
Successfully parsed a group of options.
Opening an input file: rtmp://localhost:443/live/test.
[rtmp @ 0x2ba2160] No default whitelist set
[tcp @ 0x2ba2720] No default whitelist set
[rtmp @ 0x2ba2160] Handshaking...
[rtmp @ 0x2ba2160] Type answer 3
[rtmp @ 0x2ba2160] Server version 13.14.10.13
[rtmp @ 0x2ba2160] Proto = rtmp, path = /live/test, app = live, fname = test
[rtmp @ 0x2ba2160] Server bandwidth = 5000000
[rtmp @ 0x2ba2160] Client bandwidth = 5000000
[rtmp @ 0x2ba2160] New incoming chunk size = 4096
[rtmp @ 0x2ba2160] Creating stream...
[rtmp @ 0x2ba2160] Sending play command for 'test'Is it possible to limit the latency time to several seconds ?
Sorry for any possible mistakes - English’s not my native language.