说明:
- 我们建议你安装最新的 Wowza Media Server 以获得对直播流录制的最新补丁和功能加强。下载后,安装指南查看压缩包中的 README.txt 文件。
- 你还可以下载示例模块来了解如何使用 API 创建模块(下载 LiveStreamRecordExampleModule_3.5.zip)。查看压缩目录中的README.html 文件获得更多说明。
- 本文适用于 Wowza Media Server 3.5 或以后的版本。查看 Wowza Media Server 之前版本的 LiveStreamRecord 插件包可以查看 如何获得LiveStreamRecord 插件、API 和示例。
定义身份验证方法
可以在 %Wowza%/conf/VHost.xml 文件中激活 Wowza Media Server 的直播录制功能。VHost.xml 中默认的关于直播录制的配置如下:
- <HTTPProvider>
- <BaseClass>com.wowza.wms.livestreamrecord.http.HTTPLiveStreamRecord</BaseClass>
- <RequestFilters>livestreamrecord*</RequestFilters>
- <AuthenticationMethod>admin-digest</AuthenticationMethod>
- </HTTPProvider>
AuthenticationMethod 属性定义了用于控制连接到这台 HTTP 服务器的访问的验证方法。默认值admin-digest 定义了用于远程计算机连接到基于 web 的直播流录制用户接口时的摘要式身份验证。要使用这个验证方法,你必须在%wowza%/conf/admin.password 文件中为数字验证定义一个用户名和密码。使用文本编辑器打开这个文件并新添加一行用户名和密码。例如,要添加用户名myuser 和密码 mypassword:
- # Admin password file (format [username][space][password])
- #username password
- myuser mypassword
要关闭 HTTP 服务器的访问验证功能,使用文本编辑器打开 VHost.xml 并将 AuthenticationMethod 属性值改为 none。如果你想使用远程电脑通过基于 web 的界面访问它的话,并不建议这样做。
发布直播流
在录制可以 VOD 回放的文件之前你需要配置一个直播应用,然后将其发布。详细情况在《 安装并使用 Wowza 发布你的 RTMP 直播流》中已说明,本文不再赘述。
支持的文件格式
直播流的录制支持将直播流录制为 MP4 文件或者 FLV 文件。
直播流必须以以下音视频格式编码以录制为 MP4 格式:
视频
- H.264
- AAC
- MPEG-1 Layer 3 (MP3)
- Speex
Wowza Media Server 包含有一个基于 web 的用户接口进行录制直播流为点播文件的基本选项。你可以使用本地的或者远程电脑通过 UI 来控制录制过程,定义何时开始录制,何时停止,文件名以及保存位置,视频文件格式以及其他一些细节。将直播流存档为多个文件,并且切割点基于视频时间,时钟时间或者文件大小,可以:
- 确保你已经满足所有先决条件。更多信息参考 先决条件 部分。
- 启动 Wowza 多媒体服务器。更多信息,参考 启动和停止服务器(独立) 或者 启动或者停止服务器(系统服务)。
- 通过 Wowza 多媒体服务器,或者一台远程计算机,在浏览器中打开这个 URL:http://[wowza-ip-address]:8086/livestreamrecord。
- 在 Live Stream Record 页面中,点击 start recording。
点击 start recording 后,弹出 Start Recording 对话框。 - 在 Start Recording 对话框里,定义如何按需录制直播流。
在 Action 中,选择 Start Recording 来录制直播流到点播文件(这是默认设置)。然后在 Recording Options 中,选择以下选项来定义当直播流重启时要做的事情:
- Version existing file 直播流重启后录制到一个新的文件里(这是默认设置)。例如,如果你在录制直播流到myStream.mp4 文件中,直播流重启之后会录制到一个新的名为 myStream_2013-05-12-15.08.10.645-PDT_0.mp4 文件中。
- Append to existing file 直播流重启后,录制追加到现有文件(比如 myStream.mp4)。
- Overwrite existing file 直播流重启后以一个同名的新文件将现有文件覆盖掉(比如 myStream.mp4)。
把直播流录制到多个点播文件,选择以下选项来定义如何切割录制文件:
- 定义切割文件的最大值,在 Action 中,选择 Start Recording Segment By Size。然后在Segment Size 中定义文件最大值,单位是百万字节(MB)。默认大小为 10 MB。
- 定义切割文件最长时间,在 Action 中,选择 Start Recording Segment By Duration。然后在egment Duration 中定义最长时间:<hours>:<minutes>:<seconds>.<milliseconds>。默认值为 15 分钟(00:15:00.000)。
- 按照预定计划分割文件,在 Action 中,选择 Start Recording Segment By Schedule。然后在Segment Schedule 中使用 crontab 表达式来定义计划参数。默认值以每个小时的起始时间分割文件。
- Stream Format 选择录制文件的格式,只能是 MP4 或者 FLV。默认为 MP4。
- Path 定义录制文件存储在电脑的物理路径。默认情况下,文件存放在 %wowza%/content 目录。如果你想存放在其他路径,必须先确认该目录必须存在,然后定义其物理路径。
- File Name 要改变录制文件的默认输出文件名,修改默认的模版字符串。你可以添加一些有效的文件名字符并修改模版键的字符串值。关于更多使用模版字符串的信息,参考Defining filenames of recorded segments with template strings。
点击 Submit 之后,Wowza Media Server 将会开始录制直播流,并且 Wowza Media Server: Live Stream Record 页面将显示选中的选项。
注:Wowza Media Server: Live Stream Record 页面可能不会在你点击Submit 之后立即正确显示结果。你需要刷新该页面来查看正确状态:Recording in progress。
Live Stream Record 页面中,你可以点击 stop recording 来停止直播流的录制。如果你点击 split recording,Wowza Media Server 将会录制直播流到新的文件。
注:当你点击split recording 时,Wowza Media Server 会立即停止向当前录制分割文件中写数据,并打开一个新的分割文件来继续录制。如果前面的分割文件尚未超出最大视频时间,数据也会被写到新的文件。
使用 URL 查询记录直播流
你可以使用 HTTP 的 get 方法和 URL 查询参数来请求录制直播流。以下 URL 请求表示录制直播流最少需要的几个 RUL 参数。
- http://[wowza-ip-address]:8086/livestreamrecord?app=live&streamname=myStream&action=startRecording
必须的几个参数是:
- app=[app-name]
- streamname=[stream-name](必须是一个直播流)
- action=startRecording | stopRecording | splitRecordingNow | startRecordingSegmentByDuration | startRecordingSegmentBySize | startRecordingSegmentBySchedule
可以添加以下可选 URL 参数:
- option=version | append | overwrite 默认值为 version
- startonkeyframe=true | false 默认值为 false
- recorddata=true | false 默认值为 true
- outputPath=[path] 默认值是空值,意思是文件录制到默认的 Wowza Media Server 的 content 目录(%wowza%/content)。如果你想将录制的文件保存在服务器的其他位置,你必须使用完全限定路径位置(比如,C:/Content)。路径中不允许包含文件名。
- outputFile=[filename].[extension] 默认值是空值,意思是 [filename] 同 [stream-name],并且 [extension] 取决于定义的format 值。
- format=1 | 2 默认值为 2。1 = FLV,2 = MP4。
- segmentSize=[megabytes] 默认值为 10 (10 MB)。
- segmentDuration=[seconds] 默认值为 900 (15 分钟)。
- segmentSchedule=[crontab string] 参考附录获得更多信息
- http://[username]:[password]@[wowza-ip-address]:8086/livestreamrecord?app=live&streamname=myStream&action=startRecording
查看可用的直播流和录制状态
你可以在一个页面中查看可供录制的直播流列表,以及正在被录制的直播流的状态:
- http://[wowza-ip-address]:8086/livestreamrecord/index.html
以上 URL 将会打开一个页面,显示所有 Wowza Media Server 应用中所有的可用的直播流,包括那些正在被录制中的。
Wowza Media Server 3.6 提供了根据应用名过滤直播流列表的能力。要查看一个特定的应用中可以录制的直播流和录制中直播流的状态,只需在以上 URL 中添加参数 appFilter=[ app-name]:
- http://[wowza-ip-address]:8086/livestreamrecord/index.html?appFilter=live
将打开一个页面,显示 Wowza Media Server 的 live 应用中所有可用直播流,包括正在录制中的。
你可以将以上 URL 中的应用名定义为必须的,这将关闭在页面中显示所有应用的所有可用直播流的能力。在 %wowza%/conf/VHost.xml 的 <Properties> 容器中添加以下属性即可 (要确定找到正确的 <Properties> 容器 —— 在 VHost.xml 中有好几处):
- <Property>
- <Name>liveStreamRecordRequireApplicationFilters</Name>
- <Value>true</Value>
- <Type>boolean</Type>
- </Property>
编程方式录制直播流
Wowza Media Server 包含以下应用编程接口 (API),你可以使用它们实现编程方式对直播流录制的管理:
- public void startRecording(IMediaStream stream, String filePath, boolean append, Map<String, Object> extraMetadata, int splitOnTcDiscontinuity) 开始录制一个直播流,并指出当直播源不连续时是否应该分割录制。
片源不连续时可用的分割录制选项是:
SPLIT_ON_DISCONTINUITY_DEFAULTSPLIT_ON_DISCONTINUITY_ALWAYS
SPLIT_ON_DISCONTINUITY_NEVER
- public void startRecordingSegmentByDuration(IMediaStream stream, String filePath, Map extraMetadata, long duration) 开始录制一个直播流并将录制分割到指定时间 (以毫秒为单位) 的分割文件中。比如,传递15000 来获取 15 秒的文件。
- public void startRecordingSegmentBySize(IMediaStream stream, String filePath, Map extraMetadata, long size) 开始录制一个直播流并将录制分割到指定大小 (以字节为单位) 的分割文件中。比如,传递1048576 来获取一兆字节 (MB) 的文件。
- public void startRecordingSegmentBySchedule(IMediaStream stream, String filePath, Map extraMetadata, String schedule) 开始录制一个直播流并将录制分割到由 crontab 字符串指定的分割文件中。crontab 字符串定义了按分钟、小时、天、年、每月的天数、每周的天数的时间间隔。更多信息请查询Appendix: Understanding crontab expressions。
- public void splitRecordingNow() 立即分割一个活动着的录制。这一行动停止往当前录制分割文件中写数据,并将此文件关闭,然后打开一个新的分割文件继续录制。如果使用了startRecordingSegmentByDuration 来将直播分割保存,将会在视频时间达到 startRecordingSegmentByDuration 定义的值或者splitRecordingNow() 再次调用时才会将数据写进新文件。
- public void setFileVersionDelegate(ILiveStreamRecordFileVersio nDelegate delegate) 自定义一个文件版本命名约束。
- public void getCurrentDuration() 得到当前分割文件的视频时间,以秒为单位。
- public void getCurrentSize() 得到当前分割文件大小,以字节为单位。
- public void stopRecording() 停止指定直播流的录制。
定义文件版本命名约束
你可以通过实现 ILiveStreamRecordFileVersionDelegate 接口来重写直播流录制时默认的文件版本命名约束。
- public abstract String getFilename(ILiveStreamRecord recorder) 将返回一个命名写一个录制段的文件名。返回的字符串应该包含带有文件名的完整路径 (比如,c:\temp\saved\mystream_123.mp4)。
- import java.text.DateFormat;
- import java.text.SimpleDateFormat;
- public class MyDelegate implements ILiveStreamRecordFileVersionDelegate
- {
- public String getFilename(ILiveStreamRecord recorder)
- {
- String name;
- DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HHmmssSSS");
- Date date = new Date();
- try
- {
- File file = new File(recorder.getBaseFilePath());
- String oldBasePath = file.getParent();
- String oldName = file.getName();
- String oldExt = "";
- int oldExtIndex = oldName.lastIndexOf(".");
- if (oldExtIndex >= 0)
- {
- oldExt = oldName.substring(oldExtIndex);
- oldName = oldName.substring(0, oldExtIndex);
- }
- name = oldBasePath+"/"+oldName+"_"+dateFormat.format(date)+oldExt;
- file = new File(name);
- if (file.exists())
- {
- file.delete();
- }
- }
- catch (Exception e)
- {
- WMSLoggerFactory.getLogger(null).error("MyDelegate.getFilename: "+e.toString());
- // return a temp filename
- name = "temp"+dateFormat.format(date)+".tmp";
- }
- return name;
- }
- }
默认的代理允许你定义一个模版字符串来指定录制分割文件名。
- public void setFileTemplate(String template) 激活自定义文件名模版字符串。
- public String getFileTemplate() 返回当前文件名模版字符串。
这些字符串使用:
- Start Recording Segment By Size
- Start Recording Segment By Duration
- Start Recording Segment By Schedule
- ${SourceStreamName} 直播流的名字。
- ${SegmentNumber} 一个不断增长的数值,表示当前直播流已创建的分割录制文件数目,以 0 起始。
- ${RecordingStartTime} 当前录制开始的时间点。
- ${SegmentTime} 分割录制创建的时间点。
默认的文件模版字符串是为 ${SourceStreamName}_${RecordingStartTime}_${Segmen tNumber},生成如下的 MP4 的录制文件名:
myStream_2013-05-12-08.51.31.104-PDT_0.mp4
myStream_2013-05-12-08.51.31.104-PDT_1.mp4
myStream_2013-05-12-08.51.31.104-PDT_2.mp4
模版字符串示例:
${SourceStreamName}_${SegmentNumber}:
mystream_0
mystream_1
mystream_2
${SourceStreamName}_t${RecordingStartTime}_ct${Seg mentTime}:
mystream_t2013-05-12-02.34.53.102-PDT_ct2013-05-12-02.00.00.000-PDT
mystream_t2013-05-12-02.34.53.102-PDT_ct2013-05-12-02.15.00.000-PDT
mystream_t2013-05-12-02.34.53.102-PDT_ct2013-05-12-02.30.00.000-PDT
配置通知
你可以通过实现 ILiveStreamRecordNotify 接口获取当新打开一个文件时和当前录制分割文件关闭时的信息通知。
- public abstract void onSegmentStart(ILiveStreamRecord recorder) 收到一个新文件被打开的通知。
- public abstract void onSegmentEnd(ILiveStreamRecord recorder) 收到当前录制文件被关闭的通知 (数据将不再往此文件中写入)。
- public class MyListener implements ILiveStreamRecordNotify
- {
- public void onSegmentStart(ILiveStreamRecord recorder)
- {
- // Nothing to do here
- }
- public void onSegmentEnd(ILiveStreamRecord recorder)
- {
- // move completed file to storage location
- File file = new File (recorder.getCurrentFile());
- if (!file.renameTo(new File("c:/storage"+file.getName())))
- {
- WMSLoggerFactory.getLogger(null).error("MyListener.onSegmentEnd: file move failed for "+file.getAbsolutePath());
- }
- }
- }
直播源不连续时分割录制
当直播源出现不连续时,你可以为分割直播录制修改默认的表现,通过在 %wowza%/conf/[application]/Application.xml 文件尾的<Properties> 容器中 (Application.xml 文件中有若干 <Properties> 容器,要确保你修改的是正确的那个) 添加以下属性:
- <Property>
- <Name>liveStreamRecorderSplitOnTcDiscontinuity</Name>
- <Value>true</Value>
- <Type>boolean</Type>
- </Property>
注:这一属性只适用于 startRecording API,onSegment*API 常常在不连续时将直播录制分割。
使用 properties 重写直播录制参数
注:适用于 Wowza Media Server 3.5.2 (补丁 6) 之后的版本。
你可以使用以下 properties 来重写使用基于 web 的用户接口或者直播流录制 API 设置的值。
liveStreamRecordOption
- <Property>
- <Name>liveStreamRecordOption</Name>
- <Value>overwrite</Value>
- <Type>String</Type>
- </Property>
Value 有效值可以是: append、 overwrite 或者 version。
liveStreamRecordStartOnKeyFrame
- <Property>
- <Name>liveStreamRecordStartOnKeyFrame</Name>
- <Value>false</Value>
- <Type>boolean</Type>
- </Property>
liveStreamRecordRecordData
- <Property>
- <Name>liveStreamRecordRecordData</Name>
- <Value>false</Value>
- <Type>boolean</Type>
- </Property>
liveStreamRecordFilePath
- <Property>
- <Name>liveStreamRecordFilePath</Name>
- <Value>c:/content</Value>
- <Type>String</Type>
- </Property>
Value 只能包含保存录制文件的路径。不能包含一个文件名。
liveStreamRecordSegmentSize
- <Property>
- <Name>liveStreamRecordSegmentSize</Name>
- <Value>102400</Value>
- <Type>long</Type>
- </Property>
Value 值是为字节数。
liveStreamRecordSegmentDuration
- <Property>
- <Name>liveStreamRecordSegmentDuration</Name>
- <Value>10000</Value>
- <Type>long</Type>
- </Property>
Value 值是为毫秒的数目。
liveStreamRecordSegmentSchedule
- <Property>
- <Name>liveStreamRecordSegmentSchedule</Name>
- <Value>2 * * * * *</Value>
- <Type>String</Type>
- </Property>
Value 是一个有效的 crontab 字符串。
排错
- 在你开始录制之前,直播流应该在 Wowza Media Server 上是正常获取着的。
- 你不能使用不同的实例去通过基于 web 用户接口录制同一个直播流。当一个直播流的录制启动后,其他的对同一个直播流的录制请求提交时,第一个录制将被关闭,而一个新的录制将会开启以满足第二个录制的请求。
- 在回放之前,该录制必须已经完成。
- 直播流录制 API 的设计用于服务器端的录制。客户端录制,多路录制请求整合到同一流中,这种不支持。
- 当使用 onSegment* API 时:
设置 Overwrite 标识为 true 可能会导致以前录制的文件被覆盖。
Append 标识被忽略。
通过启用额外的 debug 日志检查配置
你可以通过对 %wowza%/conf/[application]/Application.xml 文件尾部的<Properties> (Application.xml 中有很多 <Properties> 容器,要确保你拿到的是正确的那个) 添加以下属性来激活直播流录制的额外 debug 日志。
- <Property>
- <Name>liveStreamRecorderDebugLog</Name>
- <Value>true</Value>
- <Type>boolean</Type>
- </Property>
debug 日志信息将被录制到 %wowza%/logs/wowzamediaserver_access.log 文件。
以下是 liveStreamRecorderDebugLog 属性激活以后的一个日志示例。如果你在录制直播流时没有得到你想要的结果,你可以使用这些日志信息来确认你的配置是否已经使用。
- comment server INFO 200 - [com.wowza.wms.vhost.VHost@62345ce0]HttpLiveStreamRecord.recordStream: action:startRecording stream:myStream format:mp4 append:false outputPath:C:\Program Files (x86)\Wowza Media Systems\Wowza Media Server 3.6.0\content outputFile:myStream.mp4 versionFile:true startOnKeyFrame:true recordData:true segmentDuration:900000 segmentSize:10485760 segmentSchedule:0 1 * * * * fileTemplate:null
注意如果你遵循 使用 properties 重写直播录制参数 介绍的办法重写了由基于 web 的用户接口或者 Application.xml 定义的录制设置,要查找类似于以下的日志信息来检查直播流录制设置。
- filePath has been overridden in application.xml, value=C:/content/myStream.mp4
- versionFile has been overridden in application.xml by liveStreamRecordOption=overwrite
- appendFile has been overridden in application.xml by liveStreamRecordOption=overwrite
- startOnKeyFrame has been overridden in application.xml, value=false
- recordData has been overridden in application.xml, value=false
- segmentSize has been overridden in application.xml, value=102400
- segmentDuration has been overridden in application.xml, value=10000
- segmentSchedule string has been overridden in application.xml, value=2 * * * * *
如何获得 LiveStreamRecord 插件、API 和示例
以下下载 LiveStreamRecord 插件包适用于 Wowza Media Server 3.1.2 或以前版本。这些插件包并不能支持 Wowza Media Server 3.5 或以后版本支持的所有直播流录制功能。要了解更多关于你自己版本的 Wowza Media Server 的 LiveStreamRecord 插件包,查看压缩目录中的 ReadMe.html 文件。
Wowza Media Server 3.0.3.08 to 3.1.2.* 版本: LiveStreamRecord_3.0.zip。
Wowza Media Server 2.0.0.04 to 2.2.4.* 版本的: LiveStreamRecord_2.0.zip。
Wowza Media Server Pro 1.7.x 版本的: LiveStreamRecord.zip。
附录:理解 crontab 表达式
在 Wowza Media Server 中,你可以使用 crontab 表达式将直播流计划性地录制到分割文件。crontab 表达式指定分割区间,以分、时、月、年、当月的天数或者每周的天数。可用的 crontab 属性是 (按顺序):
<Minute> <Hour> <Day_of_the_Month> <Month_of_the_Year> <Day_of_the_Week> <Year>
其中,
- <Minute> - 指定分割时的分钟 (介于 0 到 59之间)。
- <Hour> - 指定分割时的小时 (基于 24 小时始终的 0 到 23 的值)。
- <Day_of_the_Month> - 指定分割时的日期 (介于 0 到 31 之间)。要指定总是在每月的最后一天分割的话,配置 31.
- <Month_of_the_Year> - 指定分割时的月份。你可以通过当月月份缩写 (比如,Jan) 或者数值 (比如,1) 指定月份。
- <Day_of_the_Week> - 指定分割时在一星期的那一天。你可以通过当日缩写 (比如,Mon) 或者数值 (比如,1) 指定日期。
- <Year> - 指定分割时在哪一年 (比如,2013)。