「蓝小飞」——前往未来世界
没有足够的数据
XiNGRZ 关注了标签 · 2019-12-26
iFLYOS 是科大讯飞提供的一款智能物联网操作系统,它聚合了讯飞语音唤醒、声纹识别、语义理解、语音合成等各项强大技术能力,旨在实现人机交互无障碍,使人与机器之间可以通过自然的语音交互方式,进行持续,双向,自然地沟通。
iFLYOS 是科大讯飞提供的一款智能物联网操作系统,它聚合了讯飞语音唤醒、声纹识别、语义理解、语音合成等各项强大技术能力,旨在实现人机交互无障碍,使人与机器之间可以通过自然的语音交互方式,进行持续,双向,自然地沟通。
关注 0
XiNGRZ 评论了文章 · 2018-08-29
最近在做的一个小项目需要用到相关技术,找到这篇文章貌似不错,于是就翻译转载上来了。
Recently I'm interesting in these technologies and I'm working on a project related to it. I've found this useful article so I translated and posted it here.原文地址 / Original post:
HTML5 Live Video Streaming via WebSockets - PhobosLab
笔者之前做一个实时监控应用的时候,曾搜索过一些将 iPhone 的摄像头拍摄的画面实时传输到浏览器的方案,一个都没有。
就 HTML5 来说,视频(实时)直播是一个很悲催的活,HTML5 视频目前还没有一个正式的流式传输支持,Safari 支持很蹩脚的 HTTP Live Streaming 并且也即将有 Media Source Extension 规范和 MPEG-DASH。但所有这些方案都是将视频分成小片,由浏览器单独下载,因此会产生最小五秒钟的延迟。
下面是一个完全不同的方案,可以支持所有现代浏览器:Firefox、Chrome、Safari、Mobile Safari、Android 版 Chrome 甚至是 IE10。
这套方案向后兼容,没有用到什么新奇技术,目前暂时不支持音频。但它出乎意料地好用。
来自摄像头的视频被 ffmpeg 编码,然后通过 HTTP 传递给一个 Node.js 写的小脚本;脚本会将这条 MPEG 视频流通过 WebSockets 分发给所有链接的浏览器;浏览器使用 JavaScript 解码 MPEG 视频流并将解码后的画面渲染到 Canvas 元素上。
你甚至可以用树莓派来传输视频。可能会有点慢,但是笔者测试过以 30fps 的帧率实时编码 320x240 视频不成问题。对笔者来说这是最好的树莓派视频方案。
下面是构建步骤。首先你需要取得最新版本的 ffmpeg,最新的安装包可以从 deb-multimedia 获得。如果你使用 Linux,你的摄像头应该在位于 /dev/video0
或 /dev/video1
;在 OS X 或 Windows 上你可以用 VLC。
确保用来分发视频流的服务器安装了 Node.js。下载 phoboslab/jsmpeg 项目的 stream-server.js 脚本。安装 WebSocket 包 ws
并启动服务器:
npm install ws
node stream-server.js 你的密码
这里的密码是用来确保不会有好奇宝宝来劫持你的视频流用的。如果服务器运行正常,你应该会看到这样的输出:
Listening for MPEG Stream on http://127.0.0.1:8082/<secret>/<width>/<height>
Awaiting WebSocket connections on ws://127.0.0.1:8084/
服务器启动后,你就可以启动 ffmpeg 并将它指向到正在运行的这个域名和端口了:
ffmpeg -s 640x480 -f video4linux2 -i /dev/video0 -f mpeg1video -b 800k -r 30 http://example.com:8082/你的密码/640/480/
这条命令会开始从摄像头捕捉 640x480 的视频,并编码成 30fps 码率 800kbps 的 MPEG 视频。编码后的视频会通过 HTTP 被发送到所指定的服务器和端口。确保密码正确,URL 中的长和宽也需要正确指定,否则服务器无法正确判断当前的分辨率。
在树莓派上你可能需要将分辨率降至 320x240 来确保编码速度仍能维持 30fps。
要观看直播,需要从前文提到的 jsmpeg 项目中下载 stream-example.html 和 jsmpg.js 文件,更改 stream-example.html 中的 WebSocket URL 为你的服务器地址,并使用你喜欢的浏览器打开。
如果一切正常,你就能看到少于 100ms 延迟的流畅的摄像头画面。很好很强大对不?
更便捷的方案请围观原文的 Instant Webcam。
只是备忘一下,近期会再发一篇博文来总结一下各个方案的实际使用效果。查看原文重复一次原文地址 / Original post:
HTML5 Live Video Streaming via WebSockets - PhobosLab
最近在做的一个小项目需要用到相关技术,找到这篇文章貌似不错,于是就翻译转载上来了。Recently I'm interesting in these technologies and I'm working on a project related to it. I've found this useful article so I translated and posted it here.原文地址...
XiNGRZ 关注了标签 · 2014-09-16
an open source project to pack, ship and run any application as a lightweight container ! By Lock !
an open source project to pack, ship and run any application as a lightweight container ! By Lock !
关注 36778
XiNGRZ 提出了问题 · 2014-07-25
:
为分割的第一段确为 Access Key 的 base64 编码;第三段确为 put policy 的 json 的 base64 编码(如果这个都能错就是你们 Ruby SDK 的问题)def upload_token
put_policy = Qiniu::Auth::PutPolicy.new 'xxxxxx'
put_policy.fsize_limit = "20971520"
put_policy.mime_limit = "image/*;video/*"
token = Qiniu::Auth.generate_uptoken(put_policy)
render json: {token: token}, status: :created
end
@Multipart
@POST("/")
void upload(@Part("file") CountingTypedStream stream,
@Part("token") TypedString token,
Callback<UploadResult> callback);
产生的请求体如下(省略 file part。SF 你又擅自着色我的代码了!):
--667fdbb3-301f-4f25-ab8d-acc80ca14192
Content-Disposition: form-data; name="token"
Content-Type: text/plain; charset=UTF-8
Content-Length: 202
Content-Transfer-Encoding: binary
Y0这是我的AK无误t5:1o1Ic这里也没问题42UVEo=:eyJzY这一串也没问题KiJ9
--667fdbb3-301f-4f25-ab8d-acc80ca14192--
返回给我的东西(取自日志):
07-24 22:59:43.266 D/Retrofit﹕ <--- HTTP 401 http://upload.qiniu.com/ (13126ms)
07-24 22:59:43.266 D/Retrofit﹕ : HTTP/1.1 401 Unauthorized
07-24 22:59:43.266 D/Retrofit﹕ Access-Control-Allow-Headers: X-File-Name, X-File-Type, X-File-Size
07-24 22:59:43.266 D/Retrofit﹕ Access-Control-Allow-Methods: OPTIONS, HEAD, POST
07-24 22:59:43.266 D/Retrofit﹕ Access-Control-Allow-Origin: *
07-24 22:59:43.266 D/Retrofit﹕ Cache-Control: no-store, no-cache, must-revalidate
07-24 22:59:43.266 D/Retrofit﹕ Connection: close
07-24 22:59:43.266 D/Retrofit﹕ Content-Length: 39
07-24 22:59:43.266 D/Retrofit﹕ Content-Type: application/json
07-24 22:59:43.266 D/Retrofit﹕ Date: Thu, 24 Jul 2014 14:59:43 GMT
07-24 22:59:43.266 D/Retrofit﹕ Pragma: no-cache
07-24 22:59:43.266 D/Retrofit﹕ Server: nginx/1.4.4
07-24 22:59:43.266 D/Retrofit﹕ X-Android-Received-Millis: 1406213983252
07-24 22:59:43.266 D/Retrofit﹕ X-Android-Response-Source: NETWORK 401
07-24 22:59:43.266 D/Retrofit﹕ X-Android-Selected-Transport: http/1.1
07-24 22:59:43.266 D/Retrofit﹕ X-Android-Sent-Millis: 1406213970562
07-24 22:59:43.266 D/Retrofit﹕ X-Content-Type-Options: nosniff
07-24 22:59:43.266 D/Retrofit﹕ X-Log: UP:17/401
07-24 22:59:43.266 D/Retrofit﹕ X-Reqid: JUAAAFZBtNkq4IMT
07-24 22:59:43.266 D/Retrofit﹕ X-Via: 1.1 gzqxg204:1 (Cdn Cache Server V2.0)
07-24 22:59:43.274 D/Retrofit﹕ {"error":"invalid put policy encoding"}
07-24 22:59:43.274 D/Retrofit﹕ <--- END HTTP (39-byte body)
--4da8f9b3-4e83-483b-b206-96faf1c4574d
Content-Disposition: form-data; name="token"
我是PutPolicy肯定没问题啦啦啦啦啦啦
--4da8f9b3-4e83-483b-b206-96faf1c4574d
Content-Disposition: form-data; name="file"; filename="stream_file"
Content-Type: application/octet-stream
文件内容
--4da8f9b3-4e83-483b-b206-96faf1c4574d--
完全按照 http://developer.qiniu.com/docs/v6/api/reference/up/upload.html 的格式构建,Header 不多不少。
已自己检查 upload token,以 : 为分割的第一段确为 Access Key 的 base64 编码;第三段确为 put policy 的 json 的 base64 编码(如果这个都能错就是你们 Ruby SDK 的问题)
关注 0 回答 0
XiNGRZ 发布了文章 · 2014-07-19
本来很抗拒 Retrofit 的,结果前几天在车上无聊想了一下,诶这玩意其实挺美的啊!
在 21 世纪 10 年代还需要自己拷贝 jar 包的库都是耍流氓。—— 我说的
dependencies {
compile 'com.squareup.retrofit:retrofit:1.6.1'
}
Gradle 是什么自己恶补去。
我喜欢对照着 Resource 来声明 API。
public interface Greet {
@FormUrlEncoded
@POST("/greets")
void create(@Field("message") String message, Callback<Void> callback);
}
public class YeahApi {
private static final String ENDPOINT = "https://api.yeah.xingrz.us";
// 让 Gson 自动将 API 中的下划线全小写式变量名转换成 Java 的小写开头驼峰式
private static final Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
private static final RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.setConverter(new GsonConverter(gson))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("User-Agent", "Yeah/" + BuildConfig.VERSION_NAME);
request.addHeader("Accept", "application/json");
}
})
.build();
private static final Greet GREET_API = adapter.create(Greet.class);
public static Greet greet() {
return GREET_API;
}
}
YeahApi.greet().create("Hello world!", new Callback<Void>() {
@Override
public void success(Void aVoid, Response response) {
// ...
}
@Override
public void failure(RetrofitError error) {
// ...
}
});
查看原文本来很抗拒 Retrofit 的,结果前几天在车上无聊想了一下,诶这玩意其实挺美的啊! 引入 在 21 世纪 10 年代还需要自己拷贝 jar 包的库都是耍流氓。—— 我说的 {代码...} Gradle 是什么自己恶补去。 声明 API 我喜欢对照着 Resource 来声明 API。 {代码...} 构建类 {代...
赞 0 收藏 1 评论 0
查看全部 个人动态 →
(゚∀゚ )
暂时没有
很好
注册于 2013-10-22
个人主页被 1.4k 人浏览
推荐关注