-
-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
collaborative editing #33
Comments
We definitely need collaborative editing! This issue should possibly wait for #28 , as it is tightly coupled with the editor implementation. Omicron666 also mentioned we could use yjs, which is also used by glicol and gibber. There are already codemirror 6 bindings in the making. |
Perhaps we can start with audio streaming. The main goal would be to capture and stream external sources, eventually driven but the underline collaborative code. This is a typical use case in ensembles based on external midi gear or additional SynthDefs in supercollider. I would say that in terms of architecture, might also be a good starting point. |
Audio streaming alone would be nice too, but we should keep in mind that if we add collaborative editing later, it would ideally run through the same p2p connection as the audio (?). I imagine collaborative editing can be tricky to get right when writing from scratch (opposed to using readymade solution like yjs), but I might be wrong. At least something to be aware of.. |
It makes sense, but I still wouldn't prioritise the collaborative editor over the underlying real-time communication strategy. For example: if instead of PeerJS we use y-webrtc I think we would be able to retrieve some sort of session context that y-* packages rely on. Main example for y-codemirror, clearly expose a provider based on webrtc: import * as Y from 'yjs'
import { CodemirrorBinding } from 'y-codemirror'
import { WebrtcProvider } from 'y-webrtc'
import CodeMirror from 'codemirror'
const ydoc = new Y.Doc()
const provider = new WebrtcProvider('codemirror-demo-room', ydoc)
const yText = ydoc.getText('codemirror')
const yUndoManager = new Y.UndoManager(yText)
const editor = CodeMirror(editorDiv, {
mode: 'javascript',
lineNumbers: true
})
const binding = new CodemirrorBinding(yText, editor, provider.awareness, { yUndoManager }) In the class WebrtcProvider, the peer field is an instance of Peer from the simple-peer library. According to this example, Peer have an easy entry point for attaching a media stream to an existing instance. In the context of WebrtcProvider, that instance would be located under provider.peer: var Peer = require('simple-peer')
// get video/voice stream
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(gotMedia).catch(() => {})
function gotMedia (stream) {
var peer1 = new Peer({ initiator: true, stream: stream })
var peer2 = new Peer()
peer1.on('signal', data => {
peer2.signal(data)
})
peer2.on('signal', data => {
peer1.signal(data)
})
peer2.on('stream', stream => {
// got remote video stream, now let's show it in a video tag
var video = document.querySelector('video')
if ('srcObject' in video) {
video.srcObject = stream
} else {
video.src = window.URL.createObjectURL(stream) // for older browsers
}
video.play()
})
} |
great! looks like compatibility is given with minor adjustments. so nothing to worry with peerjs i guess. |
Something like this would probably do. Can be a function provided by the package: ...
const ydoc = new Y.Doc()
const provider = new WebrtcProvider('codemirror-demo-room', ydoc)
const yText = ydoc.getText('codemirror')
const yUndoManager = new Y.UndoManager(yText)
...
export const bindCodemirrorEditor = (editor) =>
new CodemirrorBinding(yText, editor, provider.awareness, { yUndoManager }) |
I'm un-assigning myself. Due to conflict of interest with my current position I cannot publish open-source code related to this particular subject. |
tried out yjs the other day: https://codesandbox.io/s/collab-editor-demo-cge8hx?file=/src/index.js |
I use yjs on sequencer.party for syncronizing any text documents, as well as the state of each WAM plugin. It is stable, in that when calling the functions, they return as expected and do what you would expect. However, because every document edit is saved for reversability, documents grow in size quickly and subsequent edits begin to take longer and longer. This quickly collides with audio scheduling on the main thread and you will have sequencer skips every time the document is updated. The solution for me was to move all yjs calls to their own worker thread. I used and enjoyed https://threads.js.org. |
good to know, thanks for the hint. there is also comlink |
just dumping this from chat here, so it won't get forgotten yaxu — 03/01/2023 11:57 AM
froos — 03/01/2023 12:02 PM yaxu — 03/01/2023 12:45 PM froos — 03/01/2023 12:53 PM yaxu — 03/01/2023 12:56 PM |
This looks pretty slick: https://github.com/automerge/automerge-codemirror Relevant thread: https://twitter.com/geoffreylitt/status/1722334532546810089 |
automerge looks cool, seems it's a more general purpose implementation of crdt, yjs is probably still most optimized for collaborative editing. thread: yjs/yjs#145 |
and btw to keep this issue updated: https://next.flok.cc now supports co coding multiple strudel instances |
Hi @eilseq, just a note that I'm planning on re-implement your mininotation PRs in the next days. Please let me know if your COI has changed and if you'd prefer to redo them yourself. In any case, thanks a lot for the contributions! |
Hi @yaxu! It did change recently and I could join again, but has been some time since I've worked on this. |
Hi @eilseq, welcome back :) I should finish up my PR this evening. |
ref #943 |
I think would be interesting considering an additional package to the structure that provides real-time audio and data communication. A typical use case would be a session of multiple players collaborating on the same session.
With this application in mind, I think the library should allow a user to initiate a public session and invite other players using the generated link. This means that the library would be in charge of defining a session and return a URL invitation.
The negotiation between peers can happen without a server, despite of the topology. There are few libraries that makes this process very easy. They take over most of the required coordination to instantiate a p2p stream, reducing a lot the amount of code needed to define a real-time session.
Suggested: https://github.com/peers/peerjs
The text was updated successfully, but these errors were encountered: