生活随笔
收集整理的這篇文章主要介紹了
让FFMPEG支持实时流“伴随”转码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
FROM:http://blog.csdn.net/rcfalcon/article/details/6863119
FFMPEG命令行工具目前無法針對視頻實時流進行轉碼,而我們可以用它的新版本提供的支持TCP SERVER的特性來實現這一功能。實現邊錄邊用FFMPEG提供的命令行工具進行轉碼。(實踐證明,FFMPEG 的SDK針對實時流開發比較繁瑣,命令行工具相對來說穩定)
我們將實時流錄制成正在增長的文件,這樣問題就變成了FFMPEG如何針對正在增長的視頻文件轉碼。(首先我們保證視頻格式是可以支持正在增長文件解碼,這不在本文的討論范疇)
而我們如果直接使用它對正在增長的文件轉碼,我們會發現FFMPEG轉碼到文件末尾(轉碼速度比錄制速度快)就會退出。我們要做的就是在FFMPEG轉碼到末尾時如何將其掛起。若直接修改FFMPEG的源代碼則比較繁瑣,我們搭建一個TCP的FILE SERVER,來控制給FFMPEG發送數據的速度,而FFMPEG使用TCP的方式來獲取視頻流,即可實現這個功能。
以下是代碼,我們用python來實現:
FFMPEG version:N-32611-gd55b06b
[python] view plaincopy
??''????????import?SocketServer??import?os??import?threading??import?time????BIN_DIR?=?"bin\\"??BLOCK_SIZE?=?188*1024??FRONTOFFSET?=?1024?*?1024?*?1????gparam={'output':'','source':'','port':9333,??????????'start':0,'length':0,'ffmpeg_argvs':'',??????????'ffmpegsema':None,'tcpserversema':None}????class?MyFfmpegThread(threading.Thread):?????????def?run(self):??????????if?os.path.exists(gparam['output']):??????????????os.remove(gparam['output'])??????????argvs?=?gparam['ffmpeg_argvs'].replace("[filelocate]","tcp://127.0.0.1:%d"%gparam['port'])?+?"?"?+?gparam['output']??????????cmd?=?"%s\\avconv?%s"%(BIN_DIR,argvs)??????????os.system(cmd)??????????gparam['ffmpegsema'].release()????class?MyTcpServerThread(threading.Thread):??????????def?run(self):??????????while?True:??????????????try:??????????????????ADDR?=?("127.0.0.1",?gparam['port'])??????????????????self.tcpServ?=?SocketServer.ThreadingTCPServer(ADDR,?MyRequestHandler)??????????????????break??????????????except?Exception,e:??????????????????print?str(e)??????????????????print?"port:%d?被占用..更換"%gparam['port']??????????????????gparam['port']+=1??????????self.tcpServ.serve_forever()????????????????def?close(self):??????????self.tcpServ.shutdown()??????????self.tcpServ.server_close()????class?MyRequestHandler(SocketServer.BaseRequestHandler):?????????def?handle(self):??????????print?'connected?from:',?self.client_address????????????????file?=?open(gparam['source'],"rb")????????????????????startoffset?=?gparam['start']??????????if?startoffset<0:startoffset=0????????????????????????print?"start?offset="+str(startoffset)??????????file.seek(startoffset)????????????????????left?=?gparam['length']??????????while(True):??????????????try:??????????????????if(left<BLOCK_SIZE?and?left!=-1):??????????????????????buffer_size?=?left??????????????????else:??????????????????????buffer_size?=?BLOCK_SIZE??????????????????data=file.read(buffer_size)????????????????????????????????????????????????????????????????????????if?not?data:??????????????????????print?"data?empty!?read?to?file_end,wait.."??????????????????????finish_filename=gparam['source'].replace(os.path.splitext(gparam['source'])[1],".finish")??????????????????????if(os.path.exists(finish_filename)):??????????????????????????print?".finish?file?founded"??????????????????????????break??????????????????????time.sleep(1)??????????????????????continue????????????????????self.request.sendall(data)????????????????????????????????????if(left!=-1):???????????????????????left?-=?buffer_size??????????????????????if(left<=0):??????????????????????????print?"transfer?finished"??????????????????????????break??????????????????if(len(data)<buffer_size):???????????????????????finish_filename=gparam['source'].replace(os.path.splitext(gparam['source'])[1],".finish")??????????????????????if(os.path.exists(finish_filename)):??????????????????????????print?".finish?file?founded"??????????????????????????break??????????????????????else:??????????????????????????print?"read?to?file_end,wait.."??????????????????????????time.sleep(1)??????????????except:??????????????????print?"exception?occured,client?stopped"??????????????????break??????????print?"work?finished"??????????file.close()??????????gparam['tcpserversema'].release()????????????def?ffmpegex(source,output,start,length,ffmpeg_argvs):??????gparam['source']=source??????gparam['output']=output??????gparam['start']=start??????gparam['length']=length??????gparam['ffmpeg_argvs']=ffmpeg_argvs????????????try:??????????while?True:??????????????gparam['ffmpegsema']=threading.Semaphore(0)??????????????gparam['tcpserversema']=threading.Semaphore(0)??????????????tcpServerThread?=?MyTcpServerThread()??????????????tcpServerThread.start()??????????????MyFfmpegThread().start()????????????????????????????gparam['ffmpegsema'].acquire()??????????????gparam['tcpserversema'].acquire()??????????????tcpServerThread.close()????????????????????????????filesize?=?os.path.getsize(gparam['output'])??????????????if(filesize<length/10):???????????????????if?gparam['start']==0:?return?False??????????????????if?gparam['start']-FRONTOFFSET>=0:??????????????????????gparam['start']-=FRONTOFFSET??????????????????else:??????????????????????gparam['start']=0??????????????else:??????????????????return?True??????except:??????????return?False????????????if?__name__?==?"__main__":????????????for?i?in?range(0,100):??????????import?random??????????start?=?random.randrange(0,1024*1024*1024)??????????print?ffmpegex('C:\\16942.ts','C:\\test2\\%d-%d.wmv'%(i,start),start,1024*1024*5,\?????????????????????????"-i?[filelocate]?-acodec?wmav2?-vcodec?wmv2?-qscale?1?-ab?256k?-r?25")???????????????????
總結
以上是生活随笔為你收集整理的让FFMPEG支持实时流“伴随”转码的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。