本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
排除 Kinesis 视频流故障
使用以下信息来解决亚马逊 Kinesis Video Streams 遇到的常见问题。
排查一般问题
本节介绍您在使用 Kinesis Video Streams 时可能遇到的一般问题。
问题
延迟太高
延迟可能是由发送到 Kinesis Video Streams 服务的片段持续时间造成的。降低创建者与服务间延迟的一种方法是配置媒体管道,以缩短片段持续时间。
要减少每个片段中发送的帧数,请减少以下值kinesis_video_gstreamer_sample_app.cpp
:
g_object_set(G_OBJECT (data.encoder), "bframes", 0, "key-int-max",
45
, "bitrate", 512, NULL);
注意
由于视频渲染的内部实现,Mozilla Firefox 浏览器中的延迟较高。
排除 API 问题
本节介绍您在使用 Kinesis Video Streams 时可能遇到的 API 问题。
问题
错误:“Unknown options”
下列错误可导致 GetMedia
和 GetMediaForFragmentList
失败:
Unknown options: <filename>.mkv
如果您使用类型为 output
的 json
配置了 Amazon CLI,则会发生此错误。使用默认输出类型 (none
) 重新配置 Amazon CLI。有关配置的信息Amazon CLI,参见配置在Amazon CLI命令参考。
错误:“Unable to determine service/operation name to be authorized(无法确定要授权的服务/操作名称)”
下列错误可导致 GetMedia
失败:
Unable to determine service/operation name to be authorized
如果未正确指定终端节点,则可能会发生此错误。获取终端节点时,请务必在中包含以下参数GetDataEndpoint
调用,具体取决于要调用的 API:
--api-name GET_MEDIA --api-name PUT_MEDIA --api-name GET_MEDIA_FOR_FRAGMENT_LIST --api-name LIST_FRAGMENTS
错误:“Failed to put a frame in the stream(无法将帧放入流)”
下列错误可导致 PutMedia
失败:
Failed to put a frame in the stream
如果连接或权限不适用于服务,则可能会发生此错误。在 Amazon CLI 中运行以下命令,并确认可检索到流信息:
aws kinesisvideo describe-stream --stream-name
StreamName
--endpointhttps://ServiceEndpoint.kinesisvideo.region.amazonaws.com
如果呼叫失败,请参见故障排除Amazon CLI错误了解更多信息。
错误:“服务在最终完成之前关闭了连接AckEvent已收到”
下列错误可导致 PutMedia
失败:
com.amazonaws.SdkClientException: Service closed connection before final AckEvent was received
如果未正确实施 PushbackInputStream
,则可能会发生此错误。验证unread()
方法已正确实现。
错误:“STATUS_STORE_OUT_OF_MEMORY”
下列错误可导致 PutMedia
失败:
The content store is out of memory.
当内容存储没有分配到足够的大小时,会发生此错误。要增加内容存储的大小,请增加 StorageInfo.storageSize
的值。有关更多信息,请参阅StorageInfo:
对 HLS 问题进行故障排除
本节介绍在 Kinesis 视频流中使用 HTTP 直播 (HLS) 时可能遇到的问题。
检索 HLS 流会话 URL 成功,但在视频播放器中播放失败
当使用 GetHLSStreamingSessionURL
可以成功检索 HLS 流会话 URL,但将该 URL 提供给视频播放器后视频无法播放时,就会出现这种情况。
要排查这种情况,请尝试以下操作:
-
确定视频流是否在 Kinesis Video Streams 控制台中回放。考虑控制台显示的任何错误。
-
如果片段持续时间少于 1 秒,则增加到 1 秒。如果片段持续时间太短,则该服务可能会限制播放器,因为它请求视频片段的频率过高。
-
验证每个 HLS 流会话 URL 是否在被唯一的用户使用。如果多个播放器正在使用单个 HLS 流会话 URL,服务可能会收到过多的请求并限制这些播放器。
-
确认您的播放器支持您为 HLS 直播会话指定的所有选项。为以下参数尝试其他值组合:
-
ContainerFormat
-
PlaybackMode
-
FragmentSelectorType
-
DiscontinuityMode
-
MaxMediaPlaylistFragmentResults
某些媒体播放器(如 HTML5 和手机播放器)通常仅支持 fMP4 容器格式的 HLS。其他媒体播放器(如 Flash 和自定义播放器)可能仅支持 MPEG TS 容器格式的 HLS。我们建议尝试一下
ContainerFormat
开始故障排除的参数。 -
-
验证每个片段是否具有一致的轨道数。验证流中的片段在既有音频和视频轨道又有视频轨道之间没有变化。还要验证编码器设置(分辨率和帧速率)在每个轨道的片段之间没有变化。
创建者与播放器之间的延迟过高
当捕获视频与在视频播放器中播放视频之间的延迟过高时,就会出现这种情况。
视频通过 HLS 逐个片段地播放。因此,延迟不能小于片段持续时间。延迟还包含缓冲和传输数据所需的时间。如果您的解决方案需要的延迟不到一秒,请考虑改用 GetMedia
API。
您可以调整以下参数来减少总体延迟,但调整这些参数也可能降低视频质量或提高再缓冲率。
-
片段持续时间— 片段持续时间是由视频编码器生成的关键帧频率控制的流中各个分段之间的视频量。推荐值为 1 秒。具有较短的片段持续时间意味着在将视频数据传输到服务之前等待片段完成的时间会更少。较短的片段还有助于提高服务的处理速度。但是,如果片段持续时间过短,则可能增加播放器耗尽内容且必须停止和缓冲内容的可能性。如果片段持续时间短于 500 毫秒,创建者可能会创建过多请求,从而导致服务对其进行限制。
-
比特率— 比特率较低的视频流需要更少的时间进行读取、写入和传输。但是,比特率较低的视频流通常具有较低的视频质量。
-
媒体播放列表中的片段数— 对延迟敏感的播放器只能在媒体播放列表中加载最新的片段。相反,大多数玩家都是从最早的片段开始。通过减少播放列表中的片段数量,可以缩短先前片段和新片段之间的时间间隔。如果播放列表大小较小,则在向播放列表添加新片段时出现延迟,或者播放器获取更新的播放列表时出现延迟,则可能会在播放过程中跳过片段。我们建议使用 3-5 个片段,并使用配置为仅加载播放列表中最新片段的播放器。
-
玩家缓冲区大小— 大多数视频播放器都有可配置的最小缓冲持续时间,默认值通常为 10 秒。要最大程度地减少延迟,您可以将此值设置为 0 秒。但是,这样做意味着如果出现任何延迟生成碎片,则玩家会拒绝缓冲,因为玩家没有缓冲区可以吸收延迟。
-
玩家 “赶上”— 如果缓冲区已满,视频播放器通常不会自动追踪视频缓冲区前面的播放,例如延迟片段导致播放的片段积压时。自定义播放器可通过删除帧或提高播放速度(例如,提高到 1.1 倍)以赶到缓冲区的前面来避免这一点。这会导致播放器赶上时出现震荡或加速,并且由于缓冲区大小被保持在较小水平,重新缓冲可能会更频繁。
解决 Java 问题
本节介绍如何解决在使用 Kinesis Video Streams 时遇到的常见 Java 问题。
启用 Java 日志
要解决 Java 示例和库的问题,启用和检查调试日志会很有帮助。要启用调试日志,请执行以下操作:
-
在
dependencies
节点中,将log4j
添加到pom.xml
文件:
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
在
target/classes
目录中,创建一个名为log4j.properties
的文件,该文件包含以下内容:# Root logger option log4j.rootLogger=DEBUG, stdout # Redirect log messages to console log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n log4j.logger.org.apache.http.wire=DEBUG
之后,调试日志打印至 IDE 控制台。
解决生产者库问题
此部分介绍了在采用 创建者库 时可能会遇到的问题。
问题
- 无法编译创建者开发工具包
- 视频流未显示在控制台中
- 在采用 GStreamer 演示应用程序流式处理数据时,出现错误:"Security token included in the request is invalid"
- 错误:“Failed to submit frame to Kinesis Video client”(无法将帧提交到 Kinesis 视频客户端)
- GStreamer 应用程序停止运行,OS X 上显示消息 "streaming stopped, reason not-negotiated"
- 当在 Raspberry Pi 上的 GStreamer 演示应用程序中创建 Kinesis 视频客户端时,出现错误:"Failed to allocate heap"
- 当在 Raspberry Pi 上运行 GStreamer 演示应用程序时,出现错误:"Illegal Instruction"
- 摄像机在 Raspberry Pi 上加载失败
- 在 macOS High Sierra 上未找到摄像机
- 在 macOS High Sierra 上编译时,找不到 jni.h 文件
- 在运行 GStreamer 演示应用程序时出现 Curl 错误
- Raspberry Pi 上运行时的时间戳/范围断言
- Raspberry Pi 上的 gst_value_set_fraction_range_full 断言
- Android 上的 STATUS_MKV_INVALID_ANNEXB_NALU_IN_FRAME_DATA (0x3200000d) 错误
- 已达到最大片段持续时间错误
- 使用 IoT 授权时出现“Invalid thing name passed (传递的事物名称无效)”错误
无法编译创建者开发工具包
验证所需的库是否在您的路径中。要验证这一点,请使用以下命令:
$ env | grep LD_LIBRARY_PATH LD_LIBRARY_PATH=/home/local/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp/kinesis-video-native-build/downloads/local/lib
视频流未显示在控制台中
要在控制台中显示视频流,它必须使用 H.264 以 AvCC 格式编码。如果未显示您的流,请验证以下内容:
-
如果原始流使用 Annex-B 格式,则您的 NAL 适配标志 设置为
NAL_ADAPTATION_ANNEXB_NALS | NAL_ADAPTATION_ANNEXB_CPD_NALS
。这是StreamDefinition
构造函数中的默认值。 -
您是否正确提供了编解码器私有数据。对于 H.264,这是序列参数集 (SPS) 和图片参数集 (PPS)。根据您的媒体源,此数据可从媒体源中单独检索或编码到帧中。
许多基本流采用以下格式,其中
Ab
是 Annex-B 启动代码 (001 或 0001):Ab(Sps)Ab(Pps)Ab(I-frame)Ab(P/B-frame) Ab(P/B-frame)…. Ab(Sps)Ab(Pps)Ab(I-frame)Ab(P/B-frame) Ab(P/B-frame)
如果 H.264 以 SPS 和 PPS 的形式出现在数据流中,则 CPD(编解码器私有数据)可以调整为 avCC 格式。除非媒体管道单独提供 CPD,否则应用程序可以通过查找第一个 Idr 帧(应包含 SPS 和 PPS)从帧中提取 CPD,提取两个 nalU(将是 Ab (Sps) Ab (Pps))并将其设置在 CPD 中
StreamDefinition
。
在采用 GStreamer 演示应用程序流式处理数据时,出现错误:"Security token included in the request is invalid"
如果发生此错误,则您的凭证存在问题。请验证以下内容:
-
如果您使用的是临时凭证,则您必须指定一个会话令牌。
-
请验证您的临时凭证没有过期。
-
请验证您已设置了适当的权限。
-
在 macOS 上,请验证您没有在 Keychain 中缓存凭证。
错误:“Failed to submit frame to Kinesis Video client”(无法将帧提交到 Kinesis 视频客户端)
如果发生此错误,则表明源流中的时间戳设置不正确。尝试以下操作:
-
使用最新的开发工具包示例,它可能包含能够修复您的问题的更新。
-
将高质量视频流设置为更高的比特率,如果摄像机支持,则修复源码流中的任何抖动。
GStreamer 应用程序停止运行,OS X 上显示消息 "streaming stopped, reason not-negotiated"
OS X 上的流式处理可能停止,并显示以下消息:
Debugging information: gstbasesrc.c(2939): void gst_base_src_loop(GstPad *) (): /GstPipeline:test-pipeline/GstAutoVideoSrc:source/GstAVFVideoSrc:source-actual-src-avfvide: streaming stopped, reason not-negotiated (-4)
一种可能的解决方法是从中删除帧速率参数gst_caps_new_simple
打电话进来kinesis_video_gstreamer_sample_app.cpp
:
GstCaps *h264_caps = gst_caps_new_simple("video/x-h264", "profile", G_TYPE_STRING, "baseline", "stream-format", G_TYPE_STRING, "avc", "alignment", G_TYPE_STRING, "au", "width", GST_TYPE_INT_RANGE, 320, 1920, "height", GST_TYPE_INT_RANGE, 240, 1080,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 30, 1,
NULL);
当在 Raspberry Pi 上的 GStreamer 演示应用程序中创建 Kinesis 视频客户端时,出现错误:"Failed to allocate heap"
GStreamer 示例应用程序尝试分配 512 MB 的 RAM,这可能不适用于您的系统。您可以通过降低 KinesisVideoProducer.cpp
中的以下值来减少此分配:
device_info.storageInfo.storageSize =
512
* 1024 * 1024;
当在 Raspberry Pi 上运行 GStreamer 演示应用程序时,出现错误:"Illegal Instruction"
如果您在运行 gStreamer 演示时遇到以下错误,请验证您是否已为正确的设备版本编译了应用程序。(例如,当你在 Raspberry Pi 2 上运行时,请确认你没有为 Raspberry Pi 3 进行编译。)
INFO - Initializing curl. Illegal instruction
摄像机在 Raspberry Pi 上加载失败
要检查摄像机是否已加载,请运行以下命令:
$ ls /dev/video*
如果未找到,请运行以下命令:
$ vcgencmd get_camera
该输出值应该类似于以下内容:
supported=1 detected=1
如果驱动程序无法检测到摄像机,请执行以下操作:
-
检查物理摄像机相机设置并验证其是否已正确连接。
-
运行以下命令以升级固件:
$ sudo rpi-update
-
重启设备。
-
运行以下命令以加载驱动程序:
$ sudo modprobe bcm2835-v4l2
-
验证是否已检测到摄像机:
$ ls /dev/video*
在 macOS High Sierra 上未找到摄像机
在 macOS High Sierra 上,如果有多个摄像机可用,则演示应用程序无法找到摄像机。
在 macOS High Sierra 上编译时,找不到 jni.h 文件
要纠正该错误,请将 Xcode 安装更新为最新的版本。
在运行 GStreamer 演示应用程序时出现 Curl 错误
要解决在运行 GStreamer 演示应用程序时出现的 Curl 错误,请将该证书文件/etc/ssl/cert.pem
中。
Raspberry Pi 上运行时的时间戳/范围断言
如果时间戳范围断言发生在运行时,请更新固件并重启设备:
$ sudo rpi-update $ sudo reboot
Raspberry Pi 上的 gst_value_set_fraction_range_full 断言
如果 uv4l
服务正在运行,则将显示以下断言:
gst_util_fraction_compare (numerator_start, denominator_start, numerator_end, denominator_end) < 0' failed
如果发生这种情况,请停止 uv4l
服务并重新启动应用程序。
Android 上的 STATUS_MKV_INVALID_ANNEXB_NALU_IN_FRAME_DATA (0x3200000d) 错误
如果 NAL 适配标志 对于媒体流不正确,则会出现以下错误:
putKinesisVideoFrame(): Failed to put a frame with status code 0x3200000d
如果发生此错误,请为您的媒体提供正确的 .withNalAdaptationFlags
标记(例如,NAL_ADAPTATION_ANNEXB_CPD_NALS
)。在 Android 创建者库 的以下行中提供此标记:
已达到最大片段持续时间错误
此错误在流中的媒体片段超出最大片段持续时间限制时发生。请参阅中的最大片段持续时间限制媒体和存档媒体 API 限制部分。
要解决该问题,请尝试以下操作:
-
如果您使用的是网络摄像机/USB 摄像机,请执行下列操作之一:
-
如果您使用基于关键帧的分段,请将编码器设置为在 10 秒内提供关键帧。
-
如果你没有使用基于关键帧的分段,那么在定义流时步骤 2:编写并检查代码,将最大片段持续时间限制设置为小于 10 秒的值。
-
如果你在 GStreamer 管道中使用软件编码器(比如 x264),你可以设置key-int-max属于 10 秒内的某个值。例如,设置key-int-max设置为 60,fps 设置为 30,每隔 2 秒启用一次关键帧。
-
-
如果你使用的是 RPI 摄像机,请将 keyframe-interval 属性设置为小于 10 秒。
-
如果您使用的是 IP (RTSP) 摄像机,请将 GOP 大小设置为 60。
使用 IoT 授权时出现“Invalid thing name passed (传递的事物名称无效)”错误
为了避免这个错误 (HTTP Error 403: Response: {"message":"Invalid thing name passed"}
) 当您使用 IoT 凭证进行授权时,请确保值为stream-name
(的必填参数kvssink
元素) 与的值相同iot-thingname
。有关更多信息,请参阅gStreamer 元素参数参考:
解决流解析器库问题
此部分介绍了在采用 视频流解析器库 时可能会遇到的问题。
无法从流中访问单个帧
要从您的消费者应用程序中的流媒体源访问单个帧,请验证您的数据流是否包含正确的编解码器私有数据。有关流中数据格式的信息,请参阅 数据模型。
要了解如何使用编解码器私有数据访问帧,请参阅以下测试文件GitHub网站:KinesisVideoRendererExampleTest.java
片段解码错误
如果您的片段未采用浏览器支持的 H.264 格式和级别进行正确编码,则在控制台中播放流时,您可能会看到以下错误:
Fragment Decoding Error There was an error decoding the video data. Verify that the stream contains valid H.264 content
如果出现此错误,请确认以下几点:
-
帧的分辨率与编解码器私有数据中指定的分辨率匹配。
-
已编码的帧的 H.264 配置文件和级别与编解码器私有数据中指定的配置文件和级别匹配。
-
浏览器支持配置文件/级别组合。最新的浏览器支持所有配置文件和级别组合。
-
时间戳准确且采用正确顺序,并且未创建任何重复的时间戳。
-
您的应用程序使用 H.264 格式对帧数据进行编码。