在Linux下播放与录制电视

最近,在自己的Debian 7.2 64位系统上成功安装了圆刚AverMedia C725B视频卡驱动。于是,可以使用mplayer与mencoder来看电视与录节目了。其中,用于播放电视的命令如下:

mplayer tv:// -tv driver=v4l2:device=/dev/video0:norm=PAL:alsa:adevice=hw.2,0:amode=1:audiorate=48000:forceaudio:volume=100:immediatemode=0:normid=8:input=1:buffersize=1024:width=768:height=576:outfmt=i420 -vo xv -ao sdl -aspect 4:3

但该命令存在的问题时,当电视播放一段时间后视频与音频便不再同步。

录制节目则可以用mencoder来实现:

mencoder tv:// -tv driver=v4l2:device=/dev/video0:norm=PAL:alsa:adevice=hw.2,0:amode=1:audiorate=48000:forceaudio:volume=100:immediatemode=0:normid=8:input=1:buffersize=64:width=720:outfmt=yuy2
-oac mp3lame -lameopts fast:preset=standard -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=1800 -o output.avi

上面两条命令虽然能用,但却无法实现电视节目的边放边录。通过网上的搜索(参考)和自己的测试,电视的录制与同时播放可以采用命名管道+tee+mplayer来实现。为了方便操作,写了一个脚本程序rtv,其可用三种模式运行:

  • watch:在播放电视的同时,将其存为avi文件。
  • nowatch:只录制节目不用mplayer播放。
  • onlywatch:只用mplayer看节目而不录制。

脚本首先检测用户的命令行参数输入,然后查看是否已有mencoder、tee、mplayer进程运行。若存在,则不再执行后面的部分;否则,执行如下的流程:

  1. 首先,使用mkfifo创建命名管道;
  2. 其次,用tee命令读取管道:在录制与播放的模式下(watch)将其分为两路,一路送至avi文件,一种送至mplayer用于播放;在只录制不播放的模式下(nowatch),只输出至avi文件;在纯播放模式下(onlywatch),只送至mplayer。
  3. 最后,用mencoder从/dev/video0截取视频流并输出到之前创建的命名管道。

rtv脚本内容如下:

#!/bin/bash 

# Define a function for returning a process id
function get_pid_by_name()
{
    local process_str 

    echo "Searching process $1..."
    process_str=`ps aux | grep "$1" | tr --squeeze-repeats ‘[:blank:]+‘ ‘\t‘ | cut -f 2`
    if [ -n "$process_str" ]; then
        # The process for grep appears in the second field
        process_str=`echo $process_str | cut -s -d ‘ ‘ -f 1`
        if [ -n "$process_str" ]; then
            temp_pid=$process_str
            echo "The process id is $temp_pid!"
        else
            echo "The process $1 cannot be found, perfect!"
        fi
    else
        echo "The process $1 cannot be found, perfect!"
    fi
} 

if [ -z "$1" ]; then
    echo "Please specify the recording and watching mode: watch|nowatch|onlywatch"
    exit 0
fi 

if [ "$1" != "onlywatch" ] && [ -z "$2" ]; then
    echo "Please provide the video file name to be saved!"
    exit 0
fi 

# Declare the pid as integers
declare -i temp_pid=-1 mplayer_pid=-1 mencoder_pid=-1 tee_pid=-1 

get_pid_by_name mencoder
mencoder_pid=$temp_pid
temp_pid=-1 

get_pid_by_name tee
tee_pid=$temp_pid
temp_pid=-1 

get_pid_by_name mplayer
mplayer_pid=$temp_pid
temp_pid=-1 

if [ $(($mencoder_pid!=-1 && $mplayer_pid!=-1 && $tee_pid!=-1)) = 1 ]; then
    echo "A tv recording or watching activity is now working, please exit it first!"
    exit 0
fi 

# Create FIFO named pipe
if [ ! -e "/tmp/tv.fifo" ]; then
    echo "FIFO does not exist, now being created..."
    mkfifo /tmp/tv.fifo && echo "Creating FIFO successful!"
fi 

# Start tee and mplayer
case "$1" in
    watch ) echo "Start recording tv and watch it using mplayer..."
            # Note: sudo must be used in order to make mplayer appear
            cat /tmp/tv.fifo | tee -a "${2%.avi}.avi" | sudo -u orlando DISPLAY=:0.0 mplayer -cache 5120 -ao sdl -vo xv - & ;;
    nowatch ) echo "Start recording tv without watching it..."
              cat /tmp/tv.fifo | tee -a "${2%.avi}.avi" & ;;
    onlywatch ) echo "Start watching tv without recording it..."
                # Note: "tee -a -" will not work here
                # Cache size should not be too large and 1024 kB is a reasonable value, otherwise, the response when changing the channel will be too slow
                cat /tmp/tv.fifo | tee | sudo -u orlando DISPLAY=:0.0 mplayer -cache 1024 -ao sdl -vo xv - & ;;
    * ) echo "Please specify the recording and watching mode: watch|nowatch|onlywatch"
        exit 0;
esac 

# Start mencoder to feed the video stream into FIFO
echo "Now start mencoder to capture tv..."
mencoder tv:// -tv driver=v4l2:device=/dev/video0:norm=PAL:alsa:adevice=hw.2,0:amode=1:audiorate=48000:forceaudio:volume=100:immediatemode=0:normid=8:input=1:buffersize=1024:width=768:height=576:outfmt=i420 -oac mp3lame -lameopts fast:preset=standard -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=1800 -o /tmp/tv.fifo

停止录制与播放电视的脚本stop_rtv为:

#!/bin/bash 

# Define a function for returning a process id
function get_pid_by_name()
{
    local process_str 

    echo "Searching process $1..."
    process_str=`ps aux | grep "$1" | tr --squeeze-repeats ‘[:blank:]+‘ ‘\t‘ | cut -f 2`
    if [ -n "$process_str" ]; then
        # The process for grep appears in the second field
        process_str=`echo $process_str | cut -s -d ‘ ‘ -f 1`
        if [ -n "$process_str" ]; then
            temp_pid=$process_str
            echo "The process id is $temp_pid!"
        else
            echo "The process $1 cannot be found, perfect!"
        fi
    else
        echo "The process $1 cannot be found, perfect!"
    fi
} 

# Declare pid as integers
declare -i temp_pid=-1 mplayer_pid=-1 mencoder_pid=-1 tee_pid=-1 

# Kill mencoder process
get_pid_by_name mencoder
mencoder_pid=$temp_pid
temp_pid=-1 

if [ $(($mencoder_pid!=-1)) = 1 ]; then
   # The SIGINT has no effect on mencoder processes while SIGKILL will cause loss of /dev/video0 node
   kill -2 $mencoder_pid && echo "mencoder has been killed!"
else
   echo "mencoder process does not exist!"
fi 

# Kill tee process
get_pid_by_name tee
tee_pid=$temp_pid
temp_pid=-1 

if [ $(($tee_pid!=-1)) = 1 ]; then
   kill -2 $tee_pid && echo "tee has been killed!"
else
   echo "tee process does not exist!"
fi 

# Kill mplayer process if not in nowatch mode
if [ "$1" != "nowatch" ]; then
   get_pid_by_name mplayer
   mplayer_pid=$temp_pid
   temp_pid=-1 

   if [ $(($mplayer_pid!=-1)) = 1 ]; then
      # Note: mplayer is started by using sudo, therefore when killing it, sudo should also be used
      sudo -u orlando kill -2 $mplayer_pid && echo "mplayer has been killed!"
   else
      echo "mplayer process does not exist!"
   fi
fi 

echo "TV recording and playing have been stopped!"

将上面的两个脚本与at命令结合,则可以实现定时录制与播放节目了。例如:

$ at 20:00 today
warning: commands will be executed using /bin/sh
at> rtv watch 我爱发明
at> <EOT>                        # Input Ctrl+D
job 21 at Wed Feb    5 20:00:00 2014
$ at 21:00 today
warning: commands will be executed using /bin/sh
at> stop_rtv watch
at> <EOT>                        # Input Ctrl+D
job 22 at Wed Feb    5 21:00:00 2014

由于晚上播出的电视节目大部分在第二天白天会重播,因此在自己上班的同时,这些节目便可以按计划一个不落地录下来。同时,原本需要晚上熬夜看的节目也可以保存起来等到第二天再看。

14年6月15日 与此同时,为了方便播放与停止播放,在~/.bashrc中定义了如下aliases:

alias ptv="mplayer -forceidx"
alias tv="rtv onlywatch"
alias stop_tv="stop_rtv onlywatch"

其中,ptv在调用mplayer时使用-foceidx选项强制生成index信息,从而可以在播放的时候快进或者是快退。这是由于从视频卡直接采集生成的avi文件默认没有index信息(奇怪的是甚至即便是用mplayer生成了idx文件,用其他的播放器也没有办法播放)。不过,只使用-forceidx并不会将index信息保存下来,因此,下一次再次播放的时候,还需要重新生成index,比较耗时间。为此,编写gen_idxptv_idx两个脚本程序。前者用于生成并保存index信息,后者用于在启动播放时加载已经生成的index文件。两个程序的内容如下:

gen_idx:

#!/bin/bash

mplayer -forceidx -saveidx "`basename \"$1\" \".avi\"`".idx "$1"

ptv_idx:

#!/bin/bash

mplayer -loadidx "`basename \"$1\" \".avi\"`".idx "$1"

下面的脚本程序tv_nomen,则直接使用mplayer播放视频,而不经过mencoder的中转。这也是目前看电视直播的方法。采用该方法原本的想法是能够解决电视播放一断时间后,视频变得迟缓,开始与声音不同步的问题。但事实证明该问题并不能通过直接使用mplayer播放来解决。似乎这个问题是由于系统性能不高导致的。

#!/bin/bash

# Play the tv using only mplayer: when a long time is elapsed, audio and video will be asynchronous using this method
sudo -u orlando DISPLAY=:0.0 mplayer tv:// -tv driver=v4l2:device=/dev/video0:norm=PAL:alsa:adevice=hw.2,0:amode=1:audiorate=48000:forceaudio:volume=100:immediatemode=0:normid=8:input=1:buffersize=1024:width=768:height=576:outfmt=i420 -vo xv -ao sdl -aspect 4:3 -nocache -framedrop

在Linux下播放与录制电视

时间: 2024-11-07 22:20:00

在Linux下播放与录制电视的相关文章

Linux下的屏幕录制工具XVidCap

Linux下的屏幕录制工具XVidCap Jun 05, 2008 XVidCap是Linux下的屏幕录制工具,是讲解软件使用方法.演示电脑操作的必备秘技. XVidCap大概是X windows Video Capture的缩写,未经考证. 之前是在Open Source Alternative这个网站搜索screencast找到的,准备动笔介绍一下时发现keke已经介绍过了. 文章中说下载个deb包安装就好了,我之前下载的是tar.gz,安装也着实非常麻烦,于是再罗嗦几句. 首先在这里下载,

嵌入式Linux下MP4视频录制库MP4V2移植和简介

*************************************************************************************************************************** 作者:EasyWave                                                                             时间:2014.10.31 类别:Linux应用-MP4视频录制库MP4V2

嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍

*************************************************************************************************************************** 作者:EasyWave                                                                             时间:2014.10.31 类别:Linux应用-MP4视频录制库MP4V2

linux下播放器的设计和开发

本文根据DawnLightPlayer的开发经验写成.DawnLithtPlayer是今天3月份开始,和maddrone一起在业余时间开发的一个跨平台,多线程的播放器,主要是在Linux下面开发的,文中所用示例代码均截自其中.DawnLightPlayer目前可以运行在Linux和Windows系统上,并使用VC和Python开发了GUI,支持大部分的音视频文件格式和网络流,另外新增对CMMB协议的支持,不支持 RMVB, SWF 等尚未公开协议的视频文件格式. 目录:一. 播放器的流程   1

linux实用技巧:linux下的视频录制软件xvidcap

1.xvidcap简介 在linux如果我们想要进行视频录制,那么xvidcap是一个不错的选择.Xvidcap 是一个可将屏幕上的操作过程录制下来并保存为视频的小工具.对于需要制作产品演示和教学的朋友来说,这个屏幕录像机十分实用.Xvidcap 支持生成 avi.mpeg.asf.flv.swf.mov 等视频格式,可以应用在各种场合.录制的区域也可以随意选择,显得非常方便. 我们接下来安装xvidcap,他需要用到mplayer,因为视频录制首先得有播放器么.^_^ 2.xvidcap的安装

Linux下音频编程-输出音频文件

程序实现了在Linux下播放Ok.wav的功能.程序首先调用fstat函数获得文件相关信息(主要是文件大小信息).通过malloc函数分配指定的内存空间,并将online.wav读入内存:然后,打开声卡设备文件,设置声卡参数:再调用write函数完成文件的播放. 简要的实例,代码如下: #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> #includ

在Linux终端命令行下播放音乐的命令(Ubuntu)

现在的 Linux 桌面已经发展的很好了,在桌面下播放音乐操作起来也很简单.那么我们还记得在桌面不是那么好的时候我们是怎么播放音乐的么?哎,我是想不起来了,实在是太难了. 不过现在我们可以先安装一个小软件,然后通过命令行来使用这个软件播放音乐,感觉还是很不错滴. 这个软件的名字叫:SOX,支持很多格式的音频文件,如 WAV,MP3,MPG,OGG,FLAC 等等.满足我们日常使用是足够足够的了. 好了,首先,第一步我们需要把它安装到我们的系统里. 1.打开一个终端(Ctrl+Alt+T),然后输

linux下好用的音乐播放器

本人推荐 mplayer 安装方法 sudo apt-get install mplayer 播放指令 mplayer 音乐名 关闭mplayer     pkill mplayer linux下好用的音乐播放器

linux下mplayer(ffmpeg)通过x264解码播放高清h264视频

系统环境: Linux inbank-GZ 2.6.24-16-generic #1 SMP Thu Apr 10 13:23:42 UTC 2008 i686 GNU/Linux Ubuntu 8.04 Genuine Intel(R) CPU   1250  @ 1.73GHz  * 2 1G内存 目标:能用mplayer播放H264格式的高清视频 下载相关软件 Mplayer1.1版本(包含了ffmpeg) 各类解码包codes x264 yasm + faac + faad 可以在这里下