• 让FFMPEG支持实时流“伴随”转码


    FFMPEG命令行工具目前无法针对视频实时流进行转码,而我们可以用它的新版本提供的支持TCP SERVER的特性来实现这一功能。实现边录边用FFMPEG提供的命令行工具进行转码。(实践证明,FFMPEG 的SDK针对实时流开发比较繁琐,命令行工具相对来说稳定)

    我们将实时流录制成正在增长的文件,这样问题就变成了FFMPEG如何针对正在增长的视频文件转码。(首先我们保证视频格式是可以支持正在增长文件解码,这不在本文的讨论范畴)

    而我们如果直接使用它对正在增长的文件转码,我们会发现FFMPEG转码到文件末尾(转码速度比录制速度快)就会退出。我们要做的就是在FFMPEG转码到末尾时如何将其挂起。若直接修改FFMPEG的源代码则比较繁琐,我们搭建一个TCP的FILE SERVER,来控制给FFMPEG发送数据的速度,而FFMPEG使用TCP的方式来获取视频流,即可实现这个功能。

    以下是代码,我们用python来实现:

    FFMPEG version:N-32611-gd55b06b

    #encoding=utf8
    '''
    Created on 2011-9-25

    @author: chenggong

    ffmpeg扩展工具
    '''
    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)

    #print "read data,size="+str(len(data))
    #if(left!=-1): print "left size=%d"%left
    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): #生成失败,将start提前,重做任务
    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")

    转自:http://blog.csdn.net/rcfalcon/article/details/6863119

  • 相关阅读:
    CentOS 7中搭建NFS文件共享存储服务的完整步骤
    centos 7中磁盘挂载重启后挂载失效
    smbclient 未找到命令
    Windows共享文件夹无法访问,提示“不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接”
    CentOS 7下Samba服务器的安装与配置
    Systemd 指令
    centos7安装samba快速入门
    springboot2.0集成RestTemplate
    unknown directive “stream” in /usr/local/nginx
    Nginx——stream模块
  • 原文地址:https://www.cnblogs.com/cjxiao/p/3245559.html
Copyright © 2020-2023  润新知