Sami @ Somewhere

Blog about adventures in Dart language and other (un)related things

  • About

New Demos

Posted by Sami Ylönen on April 2, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. Leave a Comment

Added some old and some new demos.

Audio only demo shows howto use WebRTC for audio conversations.

Video demo shows howto create a video conference like system.

Datachannel chat demonstrates sending arbitrary data over WebRTC data channels.

Datachannel file transfer demonstrates sending files ober WebRTC data channel.
(Currently Chrome does not support reliable data channels, so i had to create my own implementation of reliable channels over the unreliable channel currently implemented in Chrome)

Everything you see will contain bugs and is not exactly pretty. This is a work in progress and i am no web designer =)

Link to demos Demos

Link to the Github page for these examples Here (Warning: Bad and ugly code)

Slow on the coding front

Posted by Sami Ylönen on March 23, 2013
Posted in: Uncategorized. Leave a Comment

Have had an eye infection for past 2 weeks, cant see shit, cant code… =)

Web Components talk

Posted by Sami Ylönen on February 26, 2013
Posted in: Dart. Tagged: Dart, Dartlang. Leave a Comment

Seth Ladd talks about Dart and Web components.
Worth watching.

http://blog.sethladd.com/2013/02/slides-from-jfokus-talk-on-dart-and-web.html

M3 Release

Posted by admin on February 21, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. Leave a Comment

Milestone 3 has been released
http://news.dartlang.org/2013/02/new-streams-api-with-dart-milestone-3.html

This build should include a fix for my arch enemy

Now, I’m eagerly waiting for a fix to my new arch enemy and that Chrome finally implements reliable binary data channels.

Updated example

Posted by Sami Ylönen on February 20, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. 1 comment

Updated example for a simple video “conference”.

Things are going slow, but going.
Here’s an updated sample for the library which demonstrates the key parts of “getting chatting”.

Later on, when i have enough time, i’ll post an sample on howto tie all together with Nginx,
Flask and Upstart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import 'dart:html';
import 'package:dart_rtc_common/rtc_common.dart';
import 'package:dart_rtc_client/rtc_client.dart';
 
const int RECONNECT_MS = 10000;
const String MYCHANNEL = "abc";
const String CONNECTION_STRING = "ws://127.0.0.1:8234/ws";
 
/**
 * WebRTC video "conference" sample
 */
void main() {
 
  /**
   * DataSource connects to the signaling server
   */
  DataSource src = new WebSocketDataSource(CONNECTION_STRING);
 
  /**
   * ChannelClient accepts on parameter, which is the data source.
   */
  ChannelClient client = new ChannelClient(src)
  //.setChannel(MYCHANNEL) // Setting channel here sets the client to join the channel on connect
  .setRequireAudio(true) // Microphone required
  .setRequireVideo(true) // Webcam or some other video source required
  .setRequireDataChannel(false) // Set true if you want to send data over data channels
  .setAutoCreatePeer(true); // If true, creates peerconnection automicly when joining a channel
 
  /**
   * Client sets states, in this callback you can track the state changes
   * and do actions when required
   */
  client.onInitializationStateChangeEvent.listen((InitializationStateEvent e) {
    if (e.state == InitializationState.LOCAL_READY) {
      // Client has initialized local, not connected to the signaling server yet.
    }
 
    if (e.state == InitializationState.MEDIA_READY) {
      // Your local video stream is ready
    }
 
    if (e.state == InitializationState.REMOTE_READY) {
      // If you did not use .setChannel above, this is where you can join channel (Or later on if you so wish)
      client.joinChannel(MYCHANNEL);
    }
 
    if (e.state == InitializationState.CHANNEL_READY) {
      // Channel has been joined.
      // Setting channel limit to 2, which means that only 2 persons are able to join the channel.
      client.setChannelLimit(2);
    }
  });
 
  /**
   * Client has connected to the server
   */
  client.onSignalingOpenEvent.listen((SignalingOpenEvent e) {
 
  });
 
  /**
   * MediaStream available events
   * Event name subject to change to onMediaStreamAvailableEvent
   * since this carries also local media stream event
   */
  client.onRemoteMediaStreamAvailableEvent.listen((MediaStreamAvailableEvent e) {
    // Event contains a reference to PeerWrapper (e.peerWrapper) which has an id property
    // Usefull for tracking created video elements for example.
    // set the video element id to peerwrapper id.
 
    if (e.isLocal) {
      LocalMediaStream localStream = e.stream;
      // Do what is needed with your local media stream
      // someVideoElement.src = Url.createObjectUrl(localStream);
      // someVideoElement.play();
    } else {
      MediaStream remoteStream = e.stream;
      // Do what is needed with your local media stream
      // someOtherVideoElement.src = Url.createObjectUrl(remoteStream);
      // someOtherVideoElement.play();
    }
  });
 
  /**
   * MediaStream removed events
   */
  client.onRemoteMediaStreamRemovedEvent.listen((MediaStreamRemovedEvent e) {
    // Remove the video element created earlier
    // If you used the e.peerWrapper.id as an id to the video element
    // you can use that again to find the element and remove it.
  });
 
  /**
   * Callback for when you loose connection to the server
   */
  client.onSignalingCloseEvent.listen((SignalingCloseEvent e) {
    window.setTimeout(() {
      client.initialize();
    }, RECONNECT_MS);
  });
 
  client.initialize();
}

import 'dart:html'; import 'package:dart_rtc_common/rtc_common.dart'; import 'package:dart_rtc_client/rtc_client.dart'; const int RECONNECT_MS = 10000; const String MYCHANNEL = "abc"; const String CONNECTION_STRING = "ws://127.0.0.1:8234/ws"; /** * WebRTC video "conference" sample */ void main() { /** * DataSource connects to the signaling server */ DataSource src = new WebSocketDataSource(CONNECTION_STRING); /** * ChannelClient accepts on parameter, which is the data source. */ ChannelClient client = new ChannelClient(src) //.setChannel(MYCHANNEL) // Setting channel here sets the client to join the channel on connect .setRequireAudio(true) // Microphone required .setRequireVideo(true) // Webcam or some other video source required .setRequireDataChannel(false) // Set true if you want to send data over data channels .setAutoCreatePeer(true); // If true, creates peerconnection automicly when joining a channel /** * Client sets states, in this callback you can track the state changes * and do actions when required */ client.onInitializationStateChangeEvent.listen((InitializationStateEvent e) { if (e.state == InitializationState.LOCAL_READY) { // Client has initialized local, not connected to the signaling server yet. } if (e.state == InitializationState.MEDIA_READY) { // Your local video stream is ready } if (e.state == InitializationState.REMOTE_READY) { // If you did not use .setChannel above, this is where you can join channel (Or later on if you so wish) client.joinChannel(MYCHANNEL); } if (e.state == InitializationState.CHANNEL_READY) { // Channel has been joined. // Setting channel limit to 2, which means that only 2 persons are able to join the channel. client.setChannelLimit(2); } }); /** * Client has connected to the server */ client.onSignalingOpenEvent.listen((SignalingOpenEvent e) { }); /** * MediaStream available events * Event name subject to change to onMediaStreamAvailableEvent * since this carries also local media stream event */ client.onRemoteMediaStreamAvailableEvent.listen((MediaStreamAvailableEvent e) { // Event contains a reference to PeerWrapper (e.peerWrapper) which has an id property // Usefull for tracking created video elements for example. // set the video element id to peerwrapper id. if (e.isLocal) { LocalMediaStream localStream = e.stream; // Do what is needed with your local media stream // someVideoElement.src = Url.createObjectUrl(localStream); // someVideoElement.play(); } else { MediaStream remoteStream = e.stream; // Do what is needed with your local media stream // someOtherVideoElement.src = Url.createObjectUrl(remoteStream); // someOtherVideoElement.play(); } }); /** * MediaStream removed events */ client.onRemoteMediaStreamRemovedEvent.listen((MediaStreamRemovedEvent e) { // Remove the video element created earlier // If you used the e.peerWrapper.id as an id to the video element // you can use that again to find the element and remove it. }); /** * Callback for when you loose connection to the server */ client.onSignalingCloseEvent.listen((SignalingCloseEvent e) { window.setTimeout(() { client.initialize(); }, RECONNECT_MS); }); client.initialize(); }

Testing on FireFox Nightly

Posted by Sami Ylönen on February 13, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. Leave a Comment

… Did not go so well =)

At the moment, the javascript generated by dart2js, does not compute when viewed with Firefox.

this Gist is enough to throw the error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 
import 'dart:html';
 
void main() {
  RtcPeerConnection pc1 = new RtcPeerConnection(null);
  RtcPeerConnection pc2 = new RtcPeerConnection(null);
 
  pc1.onAddStream.listen((MediaStreamEvent e) {
    print("pc1 got stream");
  });
 
  pc2.onAddStream.listen((MediaStreamEvent e) {
    print("pc2 got stream");
  });
 
  pc1.onIceCandidate.listen((RtcIceCandidateEvent e) {
    if (e.candidate != null)
      pc2.addIceCandidate(e.candidate);
  });
 
  pc2.onIceCandidate.listen((RtcIceCandidateEvent e) {
    if (e.candidate != null)
      pc1.addIceCandidate(e.candidate);
  });
 
  pc1.onNegotiationNeeded.listen((Event e) {
    pc1.createOffer((RtcSessionDescription sdp) {
      pc1.setLocalDescription(sdp, _onLocalDescriptionSuccess, _onRTCError);
      pc2.setRemoteDescription(sdp, _onRemoteDescriptionSuccess, _onRTCError);
      pc2.createAnswer((RtcSessionDescription sdp2) {
        pc2.setLocalDescription(sdp2, _onLocalDescriptionSuccess, _onRTCError);
        pc1.setRemoteDescription(sdp2, _onRemoteDescriptionSuccess, _onRTCError);
      },(String s) {
      }, null);
    },(String s) {
    }, null);
 
  });
 
  if (MediaStream.supported) {
    window.navigator.getUserMedia(audio: true, video: true).then((LocalMediaStream stream) {
      pc1.addStream(stream);
      pc2.addStream(stream);
    });
  }
}
 
void _onLocalDescriptionSuccess() {
  print("local desc success");
}
 
void _onRemoteDescriptionSuccess() {
  print("remote desc success");
}
 
void _onRTCError(String error) {
  print("error $error");
}

import 'dart:html'; void main() { RtcPeerConnection pc1 = new RtcPeerConnection(null); RtcPeerConnection pc2 = new RtcPeerConnection(null); pc1.onAddStream.listen((MediaStreamEvent e) { print("pc1 got stream"); }); pc2.onAddStream.listen((MediaStreamEvent e) { print("pc2 got stream"); }); pc1.onIceCandidate.listen((RtcIceCandidateEvent e) { if (e.candidate != null) pc2.addIceCandidate(e.candidate); }); pc2.onIceCandidate.listen((RtcIceCandidateEvent e) { if (e.candidate != null) pc1.addIceCandidate(e.candidate); }); pc1.onNegotiationNeeded.listen((Event e) { pc1.createOffer((RtcSessionDescription sdp) { pc1.setLocalDescription(sdp, _onLocalDescriptionSuccess, _onRTCError); pc2.setRemoteDescription(sdp, _onRemoteDescriptionSuccess, _onRTCError); pc2.createAnswer((RtcSessionDescription sdp2) { pc2.setLocalDescription(sdp2, _onLocalDescriptionSuccess, _onRTCError); pc1.setRemoteDescription(sdp2, _onRemoteDescriptionSuccess, _onRTCError); },(String s) { }, null); },(String s) { }, null); }); if (MediaStream.supported) { window.navigator.getUserMedia(audio: true, video: true).then((LocalMediaStream stream) { pc1.addStream(stream); pc2.addStream(stream); }); } } void _onLocalDescriptionSuccess() { print("local desc success"); } void _onRemoteDescriptionSuccess() { print("remote desc success"); } void _onRTCError(String error) { print("error $error"); }

Has something to do with Object.defineProperty.

Simple video example

Posted by Sami Ylönen on February 10, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. Leave a Comment

Update!
New Sample here

Here’s a quick example howto use the dart_rtc_* libs.

Assuming that you have cloned the dart_rtc_server repo, do:


dart bin/start_channel.dart

This will start the channel server at your localhost at port 8234

then run the sample below (with modifications where required).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
import 'dart:html';
import 'package:dart_rtc_common/rtc_common.dart';
import 'package:dart_rtc_client/rtc_client.dart';
 
void main() {
  ChannelClient channelClient = new ChannelClient(new WebSocketDataSource("ws://YOURIP:YOURPORT/ws"))
  .setChannel("YOURCHANNEL")
  .setRequireAudio(true) // Microphone required
  .setRequireVideo(true) // Webcam required for this
  .setRequireDataChannel(false); // Datachannels required chrome v >= 25 with special flags
 
  channelClient.onSignalingOpenEvent.listen((SignalingOpenEvent e) {
    // If you need to initialize somethign after connection done, do it here. 
  });
 
  channelClient.onRemoteMediaStreamAvailableEvent.listen((MediaStreamAvailableEvent e) {
    // e.stream exposes the mediastream
    // currently, if you want to check if the stream is LocalMediaStream (your own)
    // you can check e.isLocal
 
    // Add the stream into a video element
    // (query("#video") as VideoElement).src = Url.createObjectUrl(e.stream);
    // Remember to press play =)
  });
 
  channelClient.onRemoteMediaStreamRemovedEvent.listen((MediaStreamRemovedEvent e) {
    // Mediastream removed, remove the video element from dom traa etc..
  });
 
  channelClient.onSignalingCloseEvent.listen((SignalingCloseEvent e) {
    // Close, reconnect.
    window.setTimeout(() {
      channelClient.initialize();
    }, 10000);
  });
 
  channelClient.initialize();
}

import 'dart:html'; import 'package:dart_rtc_common/rtc_common.dart'; import 'package:dart_rtc_client/rtc_client.dart'; void main() { ChannelClient channelClient = new ChannelClient(new WebSocketDataSource("ws://YOURIP:YOURPORT/ws")) .setChannel("YOURCHANNEL") .setRequireAudio(true) // Microphone required .setRequireVideo(true) // Webcam required for this .setRequireDataChannel(false); // Datachannels required chrome v >= 25 with special flags channelClient.onSignalingOpenEvent.listen((SignalingOpenEvent e) { // If you need to initialize somethign after connection done, do it here. }); channelClient.onRemoteMediaStreamAvailableEvent.listen((MediaStreamAvailableEvent e) { // e.stream exposes the mediastream // currently, if you want to check if the stream is LocalMediaStream (your own) // you can check e.isLocal // Add the stream into a video element // (query("#video") as VideoElement).src = Url.createObjectUrl(e.stream); // Remember to press play =) }); channelClient.onRemoteMediaStreamRemovedEvent.listen((MediaStreamRemovedEvent e) { // Mediastream removed, remove the video element from dom traa etc.. }); channelClient.onSignalingCloseEvent.listen((SignalingCloseEvent e) { // Close, reconnect. window.setTimeout(() { channelClient.initialize(); }, 10000); }); channelClient.initialize(); }

Importing pub from github

Posted by Sami Ylönen on February 10, 2013
Posted in: Dart, WebRTC. Tagged: Dart, Dartlang, WebRTC. Leave a Comment

Due to the structure change in dart_rtc_* libs, i can now import the required files from github directly:

name:  sample_pubspec
description:  A sample application

dependencies:
  unittest: 0.3.4
  browser: any
  dart_rtc_common:
    git: git://github.com/samiy-xx/dart_rtc_common.git
  dart_rtc_client:
    git: git://github.com/samiy-xx/dart_rtc_client.git

And then just…

import 'package:dart_rtc_common/rtc_common.dart';
import 'package:dart_rtc_client/rtc_client.dart';

Cleanup time

Posted by Sami Ylönen on February 10, 2013
Posted in: Dart. Tagged: Dart, Dartlang. Leave a Comment

Ended up restructuring my dart-rtc project due to not being able to “pub require” it, and in the end, it appears to be now 4 separate projects. 5th coming soon.

https://github.com/samiy-xx/dart_rtc_common

https://github.com/samiy-xx/dart_rtc_server

https://github.com/samiy-xx/dart_rtc_client

https://github.com/samiy-xx/dart_rtc_examples

Blockers..

Posted by Sami Ylönen on February 9, 2013
Posted in: Dart. Tagged: Dart, Dartlang. Leave a Comment

Frustrating bugs =)

https://code.google.com/p/dart/issues/detail?id=7030
https://code.google.com/p/dart/issues/detail?id=8361
https://code.google.com/p/dart/issues/detail?id=8370
Hopefully fixed some day

Posts navigation

← Older Entries
Newer Entries →
  • Recent Posts

    • Cryptocurrencies
    • New version of the alphabets game
    • Design tools
    • Small game
    • GigaPush (More and more so)
  • Links

    GigaPush.com
    dart_rtc_client
    dart_rtc_server
    dart_rtc_common
  • Recent Comments

    • » Simple video example Sami @ Somewhere on Updated example
  • Archives

    • October 2017
    • March 2014
    • December 2013
    • May 2013
    • April 2013
    • March 2013
    • February 2013
  • Categories

    • Dart
    • Uncategorized
    • WebRTC
  • Meta

    • Log in
    • Entries feed
    • Comments feed
    • WordPress.org
Proudly powered by WordPress Theme: Parament by Automattic.