We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Analysis Summary
Worth Noting
Positive elements
- This video provides a rare, unedited look at solving complex low-level streaming bugs (like SPS/PPS keyframe issues) within the Elixir ecosystem.
Influence Dimensions
How are these scored?About this analysis
Knowing about these techniques makes them visible, not powerless. The ones that work best on you are the ones that match beliefs you already hold.
This analysis is a tool for your own thinking — what you do with it is up to you.
Related content covering similar topics.
Build a Twitch Clone in Elixir
Peter Ullrich
The BEAM-Rust Sandwich - Julian Köpke | Code BEAM Europe 2025
Code Sync
Build a Twitch Clone in Elixir
Peter Ullrich
What Is Phoenix LiveView? (UPDATED)
The Pragmatic Studio
Trying FluxonUI: UI Components for LiveView
Peter Ullrich
Transcript
right hello everyone hey folks how you [Music] doing what's happening here my channel somebody I don't know ah hey Mitchell yeah you're did the first I guess yeah all right well you know that's cool that somebody joins in so quickly then I don't need to wait for people to trickle in um let me just you know post to all the social medias all right I also need to switch over my keyboard otherwise you hear the clock but when I do live streaming I always switch back to my old Apple keyboard but yeah it's not as nice as my knce um what's it called a hardware keyboard no with like clickity cck Keys a click click keyboard well that's hard to say all right let me uh how you doing Mitchell how's life where are you base by the way I'm going to look you up here Mitchell on no you come for the Clack why can't I find you Mitchell hurg search man Twitter is just what's the Twitter Mitchell H sometimes this is easier yeah there you go it's funny that Google has a better search engine than than twitch itself H Twitter itself hey mik yeah you're still are you still in tenie I remember meeting you in Lisbon for the conference yeah how's it going have you uh have you worked in your video course at all that you pitched to me ah just Mitch just Mitch not Mitchell sorry yeah oh cool simple B I didn't know you work for simple B nice isn't that where um the other guy also works uh what's his name Indiana oh nice Indiana Indiana oh cool close to Chicago well for it's probably for Europe for American St is probably close to Chicago for European standers was probably like halfway like what's it 10 hours driving or so Indiana you have some green there you got a Turkey Run State Park well that's nice it's also funny how everything just goes into one big city and then you have these the blocks that's always interesting to see it's literally like somebody just taking a a ruler and just like I haven't worked on the course okay by the way uh Mitch it might be easier to go on Twitch like if you go on Twitch and you send me messages I see them a bit faster than YouTube YouTube seems to be very late uh slow yeah yeah it's not me the simp but no uh not M call I meant Mitch was working for simple bat um Tav Drive oh okay that's not too bad that's not too bad yeah you get the airport there cool cool cool cool the Hest date all right well I mean we already have a a live stream rolling so I would say let's not Dilly Deli too long not sure whether you say that at all I just maybe made that up Dilly Deli but to Dilly Deli right means to like you know idle so let's not idle too much that's a term we we're familiar with so um I have very good news to share which is that the you might be thinking about D yeah Dave lucier yeah work for a while quit two weeks after you started okay yeah yeah Dave Lucia daveid dark exactly that's uh uh he works now at TV Labs better way to build a smart TV okay TV Labs AI even it's a smarter efficient um smarter faster more efficient TV testing platform that's not too bad actually I uh in my first job I met an um a developer he worked with Smart TVs and he said it's it's not great oh I see Tailwind UI um like he basically said everything is an yeah like a JavaScript application but very complex and you can also not crash the applic otherwise the whole TV crashes and you have to restart it so they basically had one huge like try try catch loop around the whole application so that if if the application would crash it would would just restart it yeah okay it says on Startup pricing funny free trial request Enterprise contact us and then you even can do so there's no no just sign up and pay oh well Anderson GitHub L ah okay that's what he worked on uh I remember um yeah what's his name again Davey right Dave I guess that's his name Dave Lucia yeah he mentioned the lure package Felixia so if you want to into like if you want to call into lure code this is what you can use probably for his uh startup all righty um yeah now I can see your your messages faster Coolio well um anyway I just wanted to share that I have good news for the live stream because we ran into an a bug uh last live stream and the live stream before already um and then I reached out to the membrane folks and Matos uh he helped me I'm not sure where his name is mattios it's it's polish so mattios I'm saying with a Portuguese um I think accent Matos anyway this guy he helped me fix the bug is he looked at the code and it was also in their example um in their life book example thing so you know he actually opened a PR which is not yet uh reviewed or merged but we I can already pull it down and yeah basically he he had some option that was missing to repeat the parameter set for frame uh was a key frames repeat SPS and PPS before key frames whatever that means I'm happy that he managed to find the bug because I would never ever in the world would have been able to find like a bug here in one like membrane in this plugin you know so good thing that we have a direct connection to these people and yeah that was like a day later he fixed it I tested it out it's working now um so we can continue right uh we have our our code here um um let's see so I just want to show you that everything's working now so if I actually start I start the the project and yeah if I just go to low CL 4000 try to keep it as it's already running which is also a little weird like it's actually replaying parts of the last Stream So I also need to do the cleanup eventually when we when we when we build a proper um application with this you know because if I stream if I start streaming then we start writing these uh m4s files and the player is fetching those right but we're not actively adding any more files so I think after a live stream finishes I just want to delete all of that stuff so that if somebody joins again they won't see just like an excerpt like a very small part of the last stream it will just show you know there's no stream available yeah but yeah uh so this is uh working now though so if I start my uh hello hello thank you for joining I think again right I've seen your uh I've seen your name before what's this oh I need to go to development twitch is this not twitch hang on where is it ah twitch there you go so I need to run my f ofmc thing and now it's streaming the video and if I refresh the page you see the video sorry I need to just disable my screen audio otherwise you will hear me double anyway so this video is not playing so if I refresh the player you can see it is going back if I had refresh you see it's playing it's just amazing it's exactly what we want it has this cool live thing so we can't just like jump you know through the live stream but if I refresh it's working uh there's even there's even like a no like still the warnings are the same but it's working so happy happy everything's nice meta question do you actually have borders around your camera and desktop and chat window or are they boxes and OBS that are carefully arranged to look like borders um no I don't think the best viewers are on XY Homeland online I'm just going to block you okay uh Mitch your question it is a template that I have designed with with my bare hands in pixel Mater let me show you here so this is pixel Mater and I measured every single Pixel here and then I just created these background boxes in light gray and then this is a background image that I'm putting as a background on my stream so and then I need to kind of in OBS you know this thing here my my camera is like a what is it like a component so to say like a source yeah I can also turn it off and then you see it so camera turn turn off I'm gone turn on you know so this is like one component I really needed to like make sure that the that I put it in here and also it actually has a so my my real camera is actually much wider than this window so I needed to have like a a mask is what they call so if I actually turn off the mask where's my filters here like here now you see that my camera is much wider but then I used like a mask to uh make it exactly you know like this this thing so that is like a masking thing and then also my my window here is this is you know what you see over there this this way uh this component also my my whole screen and then slightly resized and uh there's a trick if you do this resizing um let me show you here oh wait I can't uh so OBS IS F filtering itself out right now how do I how do I do this uh here in the screen properties hide OBS okay no hide OBS yeah so you what I wanted to say like if you actually like the screen here if you move it into the right position it's becoming like if you change anything about this like if it isn't the same if it isn't the same size in the OBS window as it is in reality like if you make it smaller or something it loses on um on accuracy like it gets pixelated and that is an issue so what you want to do is you want to right click and then you do like scale now what is it yeah scale filtering and then you can uh filter like one of these take one of these algorithms that actually makes it more crisp again and if you don't do it you might be able to see that now actually the text is much more blurry it's much more pixelated um and now if I turn it back on it's slightly sharper like at least you can read the text again it's not 100% but uh that's a trick that I found out after 3 hours of trying to make the the text um sharp and if you want to go pro like if you want to have the best text quality there is you need to make the size of this window the same size as your screen or you make your screen the same size as your window and I know that Aaron Francis for example I think he uses like a a a screen you know in the in the vertical and then he only takes one part of the screen and he mirrors that to OBS and that way he has the most um accurate like the sharpest text okay that was a a tangent sorry maybe you weren't interested in that at all but uh now it's on record so if anybody's interested in that they can just rewatch it yeah all righty so yeah this is a a template you were playing around with OBS layout the other day and I did something similar with browser Source just wanted to make sure it wasn't missing something I mean maybe I don't know maybe you have a better you did it better than I did um screen capture now I did screen capture that's why oh our browser source that might actually be might also would be good yeah anyway yeah so if you have any ideas about how I can make the text in the this one if I can make the text somehow even sharper I would be very very happy to hear about it because when I switch to the code like I blow up the text a lot um but it's still not 100% crispy you know it's like slightly but if it's big enough then it's actually fine like if you look at code you can you can read it right because it's so big but for me it's kind of hard to actually see what I'm doing because you know I only see this much code on the screen all righty anyway uh just want to yeah actually what I wanted to share with you is this uh really cool thing that now our live view here is working and I can refresh the page as often as I want it always goes back to the live stream it starts the player they're no exceptions everything's great yeah so so what I would like to do today is uh two things not sure in which order one of them is that we actually deploy this to fly and then I'm going to use uh restream which is the here which is the service I'm using for streaming right now and in here you can add different channels so I have four channels set up and I can add one more and I can add a custom rmp Channel and here I would like to add my own fly rtmp channel so like this will be uh pointing to the fly application and then ideally yeah like you you have a website where you can go and you can see the live stream that you currently see here like you see it on Twitch on YouTube wherever like I would like to move that to its own website because the second thing I would like to do is to add a chat window so that you can actually just write messages and I see them quicker than I do with like twitch or YouTube or something yeah so that would be that would be nice so what do you think which one should we do first should we do the deployment or should we just quickly set up a chat system which one is more interesting to you right some delicious coffee the fly deployment well going once going twice going three times all right the deployment it is so um yeah so one thing I thought we need to do before we actually do the deployment is uh fix two things three things um first one I want to the chat please oh yeah I'm sorry but the fly well I'm going to do the fly one I'm going to do we we could start already with fly I'm sorry maybe uh YouTube is also a little bit behind again if you want to see me more real time then uh go to Twitch um and uh I'm just going to send you my the twitch link so that you can easily join there but yeah if you're look for PJ orick you will also find it but otherwise never mind yeah no wor I don't know why I can't I can't copy paste into this uh chat field over here all right so uh yeah so then let me go back to what we actually need to do so we need to do three things before we can deploy one of them is I would like to uh change the live view in such a way that it's um have you seen okay well I don't mind being derailed uh yes I have seen the uh membrane live stream week and I can highly recommend that if you're interested in it that you go there and I also tweeted about it so here [Music] somewhere yeah this one so we have the membrane team and they are setting up this uh whole week of live streams every night at 7 p.m. um European Time Amsterdam time uh yeah we have yuse talking like he's giving a second part of his talk well we can also go to the website here so Y is giving a continuation of the latest keynote from Elixir con F and then he's mentioning project that never wear our project the dash bit team discussed and buil proof of concept for ultimately decided not to move forward with him he's going to you know spill the beans with us what Dash bit was working on but never fully uh you know released so that's interesting to see also what what kind of experiments they were running and you know where the interests liee and then we got mattios um still don't know how how to okay you know what we're just going to we're just going to learn how to how to pronounce this name together because this this is important to pronounce people's names pronunciation how to pronounce well we are looking at how to pronounce so make sure to stay tuned to the channel a name of Polish origin m m m m is how it is said in Polish in Polish MOS all right that's also how they say it in in uh Portuguese which is interesting because when people speak Portuguese and you don't know Portuguese or Polish people might think that you speak Polish when you speak Portuguese because they have this like similar sounds like Matos would also be how you pronounce it in Portuguese I am not Portuguese but my girlfriend is and I'm learning Portuguese so that's why I know this anyway so Matos from the membrane team he's going to talk about uh the boom box library that we using here also for this twitch clone so that's going to be interesting then we have Chris mord the Chris mord talking actually building a twitch clone real time in a live stream I want to see that however he's not using the boom box he's using Elixir webc so is he really building a live stream at twitch clone because twitch doesn't use webc I think they also use hls streams and and rtmp stuff so is this really a twitch clown I don't know you know I think we need to go into the live stream and and and talk to him about it no I don't want to have cheap viewers and block all righty so that's quiz um and then yeah we have Jonathan a yonatan I think kco from um a dash bit he's a creator of Life Book really really smart person he's also the current maintainer behind Elixir LS I I think yeah and he's he's really really smart yeah and he's doing a Q&A about life book NX and Bumblebee which is going to be interesting and then I have my good friend and ex colleague Philipe he is uh yeah living close to Lisbon I work with him at my last company uh he now moved to super base which also really exciting and he built the real time system uh for super base I think him and like one or two other oh sorry this Lucas Shong yeah you're right I'm sorry I mix up names a lot this guy oh wait youan CL yeah he that's a lot of text sorry youan yeah he's working on live book he's on the yeah right Mitch I'm sorry yeah you're also The Elixir tools person um with next LS yeah he's on the LSP team right yeah sorry not with elixirs but he is on the new LSP team that's why all right cool I actually am really excited about the new new LSP like I hope you can uh you can show something soon yeah anyway uh so Philipe he's gonna talk about the realtime system using Elixir which they use for super base and that is a yeah pops up thing basically you know they build pops up but then around the globe and you can connect to it through all different kinds of services like JavaScript or you know languages if you want to have a a real time system um yeah he he he built this he told talked with me about it a little bit so that's it's really really interesting stuff and yeah he's going to talk about clustering message sending process registration and other subjects I can highly recommend all of these talks okay that was a little tension but uh now you are I hope informed that you should join and if you go to this website Elixir minus- rc.org you can actually sign up for the the live stream and then they will notify you all right yeah Jon Jonathan Steve lucash and Mitch on the LSP team Jan's focus on working on Elixir core to help support LSP and Life Book stuff righty yeah that's going to be interesting stuff where you also need to uh update elixia call for the LSP stuff I think that's also I think that's one of the cool things now that you have the backing of Y and The Elixir Co team um that you know they are also like actively working with you now on how to improve elixir in order to support the LSP better maybe that was a little difficult before like where you were working on your NEX LS uh language server but then you know you were blocked by what Elixir gave you basically yeah cool I'm really really excited about that stuff yeah I don't worry live live streams are like half the time derails and tangents we have spoken about everything in this live stream already we spoken about Brazilian iron mines you know uh we've spoken about books but yeah mostly I try to keep it on Elixir all right now finally I can tell you the three things we need to do before we can deploy this to production the first one is I would like to update the live view in such a way that if the stream doesn't exist yet it basically just shows like a nothing is streaming yet message right like no live stream currently running uh and then when I start live streaming we're can to use pops up you know to notify the live view and say now our live stream is running and please connect to our live stream right so you can just like open the website and it shows like oh you know not nothing is running quite yet but then once I start pushing my data to the rtmp server it uh notifies um all the live views that are connected to the popsa broadcast and then they will actually start loading the live stream and showing it and then the last thing is also the deconne thing but I'm not sure how we could do that but uh yeah at the end of the live stream I would also like to show something like the live stream has ended or again like there is no live stream so just you know so like a little bit of ux uh so that you don't come to the website and you don't see anything and you don't know why you don't see anything so you know stuff like that so I would say let's first start with the the live view like the the the pending situation um and we're going to do that in the index live over here and uh yeah I can now use my own player so I'm going to delete the the old player that we have that's itoy this controls a play give me a topic ideas if you want to learn basally what I want to do on the let me and I'm Happ I will happily add it all right that's it I'm just going to um share come everywhere and I hope and then um cheers just live faults so when we when we join then we just say currently it's not live everywhere and I hope and if we're not live then we're not going to show the uh the player and otherwise we will just show um what what should we say here some words I'm not really good with copy Peters currently not live all right and probably yeah let's also go go to our rout and just fix our our layout here because I also don't want to show the the header and in root I want to do text white all right Peter's currently not live there you go now we can also do flex and then we do justify cont Center and item Center okay all righty and now if we set this to True also give me a top you want to learn about certain topics that you know you just want to have a okay so this is how we can get started now the next thing yeah thank you CTO now the next thing is we kind of need to have um a code some code that actually tells us well yeah the stream is actually currently running and I think what we can do is look at our attemp folder and see whether there is [Music] a um or should we make that we can also make that a global State I think so we could use an agent for that we could could use ads for that um well let's see what our options are I wrote this little thing run elix here and I also try to you know give you all the different options like for for example in memory state so we could use an agent uh to be honest that actually sounds best to me you know we could use ads but uh n maybe that's Soo much we just want to have like a single yeah we could use deaths or persistent term or G server I think I will go with an agent it's just going to be our our stream State basically and in here we can store that we say well we're currently streaming you know like true or not uh we can also what can we yeah eventually we can also have like the the the link maybe to the stream so like we hardcoded it currently to SL stream index I mean that's fine too but you know there would be a place where I can just put all my stuff um yeah and we need to start it before the rmp server because if we start our application we might already receive rtmp messages and then we want to set the state so I'm just going to uh stream state I'm just going to start it here okay and now we can do that here stream State and this is going to use an agent and I always forget the well it's just a start link with an initial State yeah so our initial State basically is uh live fs and that's it that's enough to start our agent and then yeah we can also do a get State and uh also we want to we want to have that as um as a Singleton so we're going to use our module name module Jesus and then we can also use it here yeah and yeah we can just do like um set life and we're just going to do a cast I like to actually use a little attribute a module attribute for keeping the the module name that makes it a bit easier than writing like underscore uncore module all the time like this okay yeah that should already give us enough um Power here to just keep our stream State you know now we can set it to live faults and [Music] um yeah what we can also do I think in our agent we can also use popup uh to just say well so when we we don't do a cost we do a call is it a call no we only have cost yeah cool well yeah in here I can also use the a pops up thing and say well you know if when our state changes I'm just going to broadcast popup uh broadcast stream State changed yeah should we do our broadcast inside the anous function because it's a cast right it doesn't care about the it's a fire and forget operation actually that's I wanted to use the the call instead usually with Gen servers you have calls and casts and you can use call if you want to wait for a return because in here it might actually happen that our state update doesn't work and for whatever reason but we we we never get notified about it um let me check that I think Elixir agent they might also have a call function wait how do I get to the latest we have a cost get an update might also be interesting actually wait start [Music] 24 I think get an update is what we want right we want to update the state and then we want to return it and then then we want to R uh run the Phoenix broadcast but yeah apparently agent don't have called well they have get an update I guess that is also a a call yeah let's do get an update so and yeah this receives the state and then it returns whatever they want to return and the new state so like this and then we return our state and then we can run our Phoenix broadcast from outside the the update okay all right um now we got to the live view we can also do if connected then we want to do a phoenix pup sub um subscribe for the topic stream State changed yeah and actually when we do the broadcast we want to like always have kind of like an identifier for the message so you know because if you so usually you you you um subscribe to a single topic like stream state for example and then I can can send different messages with the same topic and one of them in this case might be a like State changed um message you know but I might also have something like State reset uh State um initialized you know stuff like that but I I want to send them all through the same topic so stream State um that's why it's usually good practice to have like a tuple in every message that has an identifier as the first um argument like an an atom and then the actual um no we don't need this and then the actual message behind that right because now in my life view I can actually match against that so I need to do handle info and I can do change and then we have the stream State here right so now if I have multiple messages like uh State reset or state initialized I can just have multiple handle infos and you know can against the reset message that's why it's uh it's good practice to just have a single topic and then send different messages through it but you know not always but usually that's it's it's my first choice uh yeah okay so when we receive this we can assign to the socket um live stream State live cool all right and um yeah also when we start when we start our life here we want to look up the current life status right we want to see like are we currently streaming or not so for that I'm going to use the get State steam States and then we just do the live in here okay let's see I probably need to restart yeah restart my application yep not it's working and um let me do an i ex session here instead so now like first we see hey Peter's not live and now if we do app stream State set live to true all right that's it I hope you enjoy this it's working now our live view is running our and I hope and if we set it to fults it's gone again cool that's what we want right nice and easy okay so yeah we want to use this now in our application where we set up our rmp uh I can also delete this thing where we set up our atmp server [Music] yeah hang on guys I just got to run to the toilet real quick I'm going to be back in one second ah hi Michael no worries U it's going to be on YouTube the recording so you can watch it there e e e e e e all right folks had a quick chat with my girlfriend too sorry about that that's what they call in uh in the radio and in the television World dead air that's actually what you don't want to have where nothing is playing I'm not really good at that yet but yeah all right so [Music] um are you still there still back are you enjoying your coffee too so uh let's continue right let's just continue so I want to have two things here like I want to this is my rtmp server right and the handle new client function is the the call back that actually gets executed when I start streaming hey hi Jacob what did you missed uh you missed that we um have now our live stream running here so you know I got like a nice cool little nothing's happening and now the what we wanted to do is like when I start live streaming that the live view switches over to the live stream live stream player so we can we can do that here uh we can do app uh stream State said live to true that's what we want to have here um and then there was another thing that I want to have which is um when we stop playing that we set it to false so um I'm just going to look that up membrane uh rtmp I'm going to look for this function here because then they might also have the the opposite of it an numberous function called when a new client joins it receives the client reference app and stream key allowing custom processing yeah but that's actually what I what I was kind of fearing already because I'm you know we wouldn't know like how do we know that the client doesn't stream anymore it might just be like you know interruption in the internet but I think that's what the client time mod is for so after one second I guess that's I'm not sure what they do here time after which an unused client connection is automatically closed Falls of 5 Seconds yeah so actually we want to yeah just maybe set it to five seconds um yeah and I don't think I have a call back here for doing when that happens right it would be nice to have that actually so the client Handler handle end or stream okay so they have a call back and yeah we can set that here actually in the client Handler implementation I think if we go here we see the client Handler implementation and it has a handle connect a handle stream published handle info send me data data available end of stream here send and our stream to a pit and we have a source pit [Music] here and that is something we can set actually yeah buff for appstream key controlling process so I guess if we we can hand we can handle it in the Stream age uh stream state right I mean we would also need to ignore a lot of the S dator mechanisms sand dator to pit so yeah then um we would rece like a data and an end of stream [Music] agent well let's just yeah let's just set that up for now to see whether it actually worked oh wait here controlling process is itself but that would be my application what is the controlling process so I basically want to find out how I can tell the atmp thing to notify me when the stream ends client Handler implementation and implementation of the client Handler Behavior compatible with the rtmp source element no okay let's just do that let's set the source pit uh and we going to set it to the app stream State actually yeah I mean it's an agent not sure it's not a gen server but it should be able to handle data no it's not an agent yeah let's let's rewrite this to a gen server do we we don't want to have that as a gen server do we because if we make it a gen server then we would also receive all this information from the rmp server no I'm going to make this um another gen server so my idea my problem here is why I don't want to use this stream State thing is kind of like the stream state gets called a lot from all the clients that connect and like if we use our rtmp client like if we let the client the rmp client send data to to this uh agent yeah I mean I mean you know it won't receive that much data or that many messages but it might just be the case where this gen server gets a lot of messages from the client atmp um thing and then it's not available to our um clients like our to Life View clients so our life view clients might not be able to you know get the data they want because this same process receives us all the data from the MP client it's it's overate I know like probably this wouldn't be an issue but just to be sure I'm going to I'm going to create another gen server that we call a stream Handler and this is just going to be a a gen server and this is uh start link arguments again me arguments and then name me yeah this one is just starting like without a state and this will receive handle infos with data and then atmp data and it's just going to ignore those and then it's going to also receive the end of stream message and that's the one we we care about because in this situation we're going to call stream State set live false yeah right so let's see whether this this works um yeah the source pit so in our rtmp server we can Define The Source pit yeah it wasn't here right uh where did they say we could add options that will be added to handle info let's go back here that's our rtmp server so the handle new client function should return a client Behavior spec which defines how the client should behave if just a t pass the second element of that t+ used as an input argument for the client Handler handle in it otherwise an empty map is passed to the handle in it so we want to have a Tuple the second element of that Tuple is used as an input argument for the client Handler so that's what's the first argument cuz here this is our function and it should return a twole all the Handler and the options so our [Music] Handler but also there's a Handler thing H interesting so somehow not all the not all the options are documented right because the Handler options not documented here but um yeah p name handle new client and it should return a client Behavior spec which is either a client Handler or client Handler and options uh yeah let's just remove this one here and as a tup we want to return the client Handler implementation and options which would be Source ID Source pit will be the stream Handler okay and in the Stream Handler I'm just going to lock some stuff to say hey I received some data so that we know that actually this is uh receiving the the messages we want okay so now if I restart my my thing my server let's see what happens so I mean first nothing happens because we don't have a a client but now if I run my FFM pack thing okay key Handler not found ah so we actually running a listener wait but wait so where did the Handler option come from like it's an rtmp server and also here the options are not exhaustive apparently so only the client uh time out and they handle new client oh okay so this is the Handler so these are actually the options so what do we have here we have the function that should return any or nil no it's not any it just returns nil okay so as a Handler we have the client Handler interesting so we can't do this actually and our client Handler [Music] implementation yeah it's it doesn't have a source pit only has a controlling process yeah we can't even override the source pin I just realized because the options are just ignored in this [Music] situation it's harder than I thought to see whether a stream stream has ended or not Stay s Pit All right but actually when when it receives a message send me data then there is a source pit and that is the source okay so this is probably our client when the client starts then it sends a message to this now what is this send me data where where does send me data come from from yeah there is a call back for the end of stream but that is inside uh this client implementation and we can't extend yeah the handle end of stream call back exactly that's what you meant and that's correct but like this is like a default implementation so if we wanted to we would need to create our own Handler and then overwrite only this function which I guess is okay we can just copy paste whatever we have here but uh I I thought maybe there's an easier like um escape hatch that's that's what people say like if you give an a default implementation but you want to make it open for other people to extend easily you know then sometimes you add like uh an escape hatch where uh you can add your own stuff to it or something like that like in this situation uh you could have exposed these functions as as options you know but or maybe just like expose a call back option so say well of course this is a call back that the cl the client executes but then the options might also like you want to add a call back option so like I can give you a function that you should execute when this function is executed you know what I mean like that would make it easier to to extend this implementation of a client Handler [Music] yeah handle new clients I get yeah maybe we need to implement our own but yeah it just feels so so weird because we only need this one call back uh maybe it's not that important right I mean if I if people watch the live stream and then like I'm saying hey you know this is the end of the live stream and then they just close the way the website and the player is going to stop playing anyway but still like we are not resetting our state so the next time they join the website they will still see the the old live stream I can also just add all these things behind like I can I I might have to log in myself you know like with an admin account and then I have some special controls where I can say starts start or stop stream but I would rather like this to be uh dynamic so that I I just need to press one button in OBS and then this should finish like this should also update uh yeah you know what we can we can just do that we can just copy paste this code and edit edit it why not so actually yeah we can do that in our stream Handler why not app stream andler so yeah this just takes all the same things except for in the end when the end of stream comes we do a app um stream State and set live FS yeah and we could also move our um we could also move this thing here to the stream Handler so when it gets like a handle connected thing I'm not sure which one should be handle connected or stream published let's see callbacks types where does this come from the handles connected just a documentation is a little bit outdated it seems or maybe I'm on the wrong no it's the current version but this thing comes from the membrane rmp well [Music] Source but where where does this thing come from it's from the membrane rmp plugin yeah it should be from that library right and it implements the client Handler Behavior but this one the behavior it doesn't Define these special functions yeah it's not that important I guess it's just interesting [Music] um yeah I would just say here handle stream published that is the place where we actually set it to true because then it's published um data available end of [Music] stream and then yeah we do this is where we set the stream to false all right let's uh let's try that let's um stop this let's restart the application let's look at our okay so I'm currently not live now if I start playing the [Music] thing I'm still not live but it is playing okay that didn't work so yeah and I'll connect it maybe in here let's try this again okay so I'm currently not live I'm starting streaming I'm not live all right so none of these are actually executed in that situation I'm I'm going to edit back here so that should now work so I'm not live oh no damn it not live I'm starting my live stream hello okay I have an announcement to make yeah now we have to wait a little bit oh hello there hello there okay so if I restart the page now if I just refresh the page it's fetching the current life status and it's showing the now we have to wait all the until like all until the the end is reached so I'm just going to let this run in the background sorry you're hearing this right yeah let me turn this off again alsoo this okay um yeah so I'm I'm just going to let this run until the end and then see whether it actually updates our stream like whether it updates the state right okay but uh yeah so the the next so these were the two things like the start and the end um we don't really need to delete the folder at least not now when the stream ends we could actually do that but you know what it's it's not that important for now if I only have one stream running you know it's it's fine [Music] um yeah so I would say let's just quickly add the chat and then we can deploy this thing I would say and then we have everything together I can start streaming I I one one other thing I want to implements also kind of like an like the the end point here should be somewhat secured so that not everybody can start streaming to this port and like it can only be me basically so what I'm going to do is I'm just going to set a stream key that is uh kind of that I can set during the deployment but then yeah so I set it during the deployment and then when I connect to the the live stream I I send that key and then actually here in this function we can check whether that key is correct or not maybe but I also don't I don't see a way of like uh I I don't see a way of blocking a client so you know what I mean like if I go to the membrane rtmp again because there is a there is this one function the module rmp server and that has a call back function here the handle new client what happens yeah can I block here somehow a user how would you we can also we can look at the Alor again because they also probably need to implement this somewhere like somewhere they need to implement some some access security because otherwise people just start streaming to their rtmp server and they need to handle it right so let's maybe look at the router let's see what happens here do they have an rmp somewhere no where do they do rtmp pipeline validator yeah we could of course we can also make it a plug like we can make it a plug and then inside the plug we compare the string like the stream key that is part of the string I think the URL we can compare it to what we have previously but let's see because here they have some configuration or the rtmp port but they have um I think life was it [Music] called dogs was like a life route somewhere no maybe look at the plugs maybe in the end point probably in the end point yeah here life no but that's a life view what what's in the application are you guys still interested in this I mean we can just move on maybe this is like me just falling down the rabbit hole um but yeah what I currently try to do basically is to figure out how to do permission or access control on the the rtmp endpoint so I see here in their application they actually have an TCP server and then they have an a membrane pipeline in there m I want to find where they do their rtmp here rtmp TCP server now this seems to be it and the Alor pipeline oh well yeah they really have their own membrane pipeline here and they have a message validator yeah look they also have a toggle stream live thing funny Ando stream fults yeah and I think they have a pass Control Function here no I think that's something else are are you folks still there like if this is boring then we just move on because you know we want to get to the the cool stuff and I think [Music] um yeah but still I would like to understand how we could protect because this rtmp thing it literally just runs on the port 50002 right so it's just if we expose this one we here hey philipo you're always there thanks for being always there I I also shared the good news that you're going to talk uh in two weeks time during the live streaming week you know I I hyped I hyped everybody up for that stream I think but yeah so the last thing that I would like to do this before we deploy this is to understand how can we oh by the way our live stream did not update you know what because I'm a dumbass I didn't set up I didn't update the Handler here of course already building a web art to see super basing well if you want me to to test it with the 1 million people in the Stream let me know send me send me a message and then we look at it together your repb RTC super base thing now we can um stress test it but yeah as I said earlier I'm an idiot because um we actually need to update this thing of course otherwise it's not going to use our custom implementation of the Handler I'm an idiot so let's go here again and let's try this thing again all right now our thing is [Music] working and so I'm currently not live and if I now start my thing I am live all right and we can also just stop our stream I think manually and I'm not live we have our live not live indicator just because you know I completely forgot to actually set the Handler here but now it's working so that's great okay so then the last step would be to understand how can we actually block like a proc like how can we block a streamer from not accessing from accessing the rmp server and that is what I'm currently trying to figure out because yeah we get like a client Handler I mean that is that's basically what handles handle connected sorry so that's why I was looking at Alor here because I would like to understand how they actually it's also funny the hard Cod of some YouTube handels [Music] here coding ah here they have a validate stream key success success stream already set up terminate normal the release stream message when stream key is set with URL okay what is the release stream messages release stream yeah and they also have a validator on the pipeline here validate will stream so that's basically validate connect even messages connect okay how can we we how can we J call validate stream key yeah this is what we need we need to yeah get this messages connect and then return something where is the messages connect here rmp messages connect and we even got the message validator protocol for implementing atmp message validators allows for verifying some of the atmp messages cool how do we use this where is this used oh it's just an implementation no message relator and there's the default message validator but where can we set this thing up wait we need to go to the latest version here ah okay the the messages changed here so we got the messages connect defines the connect command to map but they don't really say where they do the validator now because like here I guess they use old version of the rmp um plug-in but the latest version it doesn't have these the validator messages anymore again where can we set this up in in our server I mean do you think we can do it in our in our clients in the handle client thing handle client so it should but it should return us back membrane protect rmp port so yeah this is our architecture here that's what we using basically so we got our stream of incoming rtmp packages do you see that and then we have an rtmp source and that goes to the H uh to the passer the video and the audio passer and then on our syn there's a sync bin which converts the whole thing to an hls sync for the video and the audio yeah and then it actually stores it to storage passes passes yeah so the rmp server it will expose a TCP Port now how do we protect this running the demo I don't know because yeah I don't want to I don't want to deploy this to production and then just open up the port to anybody and everybody and everybody can stream to this particular Port like it just just deny new clients to to connect but I don't I don't see where you can do this with with the atmp server here it just exposes the TCP port and that's it I mean I could just put it on a on a random Port but I mean that's just it's not actually um I mean they still have a couple of messages here and like I still have a feeling like we can do that in our client Handler somewhere like the handle in it stream key stream published send data yeah we can just we can just I don't know handle in it so our client Handler it has different messages has a handle in it should be return the initial state of the client Handler yeah the call back invoked when the client sends the membrane rtmp messages connect but there's no way of like blocking us damn it okay so this is where we get the publish message but again there's no blocking mechanism where we can say just don't connect to this person handshake in its server handless State server published Folds yeah I'm going to I'm going to add the membrane I'm going to ask the membrane people about this there must be an easy way CU I see it in the algora code like I I see that they have like an implementation for the message validator and in here they actually um they kind of uh let's see so that they have like a call back here in the validator and in here they yeah validate connect wait wait I had that earlier where was it um search for the symbol yeah and in the pipeline they handle call and then validate stream key they get the user by the stream key and if they don't get the user they return error inv stream key terminate normal that's what I want that's what I want but how do I implement this the message Val data I mean maybe it's in a different plugin maybe we can just do the same somehow let's do message validator automatic this is from 2024 yeah okay so because they set up their own pipeline that's why they can actually set their own message Rel data here but we don't set our own pipeline we just use uh boom box I guess boom box doesn't allow us to maybe maybe there's some hello sorry we're a little bit stuck right now because we don't know how to validate the incoming uh request the incoming streams so we want to block some streams and only allow my stream basically which has the exact right stream key and unfortunately there is no way of doing this really examples I know what I can also just do somehow is to just um explode the Gen server so when like here in our stream Handler you know um like here for example the stream published one or stream here handle connected maybe somehow I can get the stream key here and then I just don't return I just return nil and you know I see how the thing just uh explodes let's try what happens I mean if if you know sure if people connect to us server and like the process explodes I get an exception but they still can't connect to the server I just wish that there was a better way of actually like terminating the actual connection but yeah uh so I'm just going to I'm just going to print out the messages that we're getting here so that we can publish message okay so now if I stop my [Music] stream see what happens all the way somewhere Jesus lot of debug messages here here there's a connect and the connect has a URL it doesn't yet have a um how you say the stream key yeah I guess because we just ignore that m p local 202 streamer I think that's what we no like I had a stream here streamer DB 52 whatever flash TC URL publish yeah and the publish me that's where we got our stream key well okay so in our um in our publish thing if we say like publish message stream key only if it's equal to like AET thing then we do this otherwise we return nil let's see what happens here because now we can still connect so I want to loger all right let's see okay now if I just change this if I just have a random stream key then yeah it will say broken pipe um it will not play the thing there's going to be an exception here yeah Source pad not found I mean it's not great but it is killing the connection so maybe that's good enough yeah I'm I'm going to I'm also going to ask the membrane folks about the the validator thing because somehow it's gone boom box I mean maybe they moved it somewhere else but and also it would be nice it would be nice to understand where these things actually come from soour wait uh they have an example somewhere yeah I'm I'm going to give this like two more minutes and if we don't find a solution by then I'm just going to go with this this solution yeah so they have an a pipeline here okay yeah okay the example doesn't give us much information they they have a received du Loop here they wait for for uh for 10 seconds until you connect to it and then they pin the app on the stream key um yeah all right I don't know I'm not sure how to do this in the application here though because the atmp server doesn't offer me that that thing no also I don't know what this controlling process is but ah anyway it it doesn't matter too much we we have our thing it's not great we just kind of like make our gen server explode if somebody connects it it's not supposed to connect but it's it's all right I guess like yeah let's just let's continue let's continue has been enough um yeah and I'm going to I'm going to make this a a configuration thing so in runtime I'm just going to add a config for my app and that's the stream key and I'm going to get that from environment variable and otherwise I'm just going to make it abc1 23 and then in our [Music] okay I don't want to I just want to save the code here to run the streamer okay all right so [Music] um yeah so one more thing I wanted to test sorry I'm really like let me know if this is boring to you right like let me know whether we already spend way too much time on this and you just want to see me deploy this thing because then we're going to do that but I just thought like there must be a way right like it it itches my my brain to think well there must be a way of just like even if I have my client Handler already I have a client Handler and in there I should be somehow able to to just block the connection if the stream key is invalid and that's what I thought I would get from um the handle new client call back yeah I think that's the best way is what you doing yeah yeah actually so I'm curious about so this is what we this is what we need to return from uh our new our handle new client call back and in here might be yeah disconnect reason state somehow yeah that's what I thought too right because um so this one here is actually expecting a client behaviors spe I think that will be I think it will be like can we add a disconnect normal thing here right like this will be a child spec and how can you do like elixir child spec terminate you know can we like add um a return of say like hey stop don't start this gen server yeah stop reason state usually I'm just gonna I'm just gonna return this here stop uh Fubar n let's see what that does no it didn't do anything fun yeah I'm gonna ask the membran folks about this hey Vil because this would be the way the the place to do it right like handle new client and then I either have to return on okay this is my implementation like okay child's back basically or stop or error or whatever but somehow this one just ignores anything I return I mean they they say that they uh respect it so here that what they expect is either the client Handler or like a two- client Handler with option but in this situation it just ignores it completely like if I just return fuar oh this one's returning an okay pit I don't know so if I now start my thing yeah again it doesn't really matter what I return from that function so that's great yeah okay anyway I'm gonna I'm going to ask the membrane folks again because there must be a way to just say well just don't start this child all right anyway okay let's move on this this is this has been ongoing for too long um we checking the API key that handles something yeah here in the so I wanted to have the stream key and in here I wanted to get the expected stream key from application get environment so in here so let's see if I now start my thing and I abc1 2 three everything's working if I do something else f um yeah it blocked my my thing my stream cool and I get an exception oh well good enough good enough okay so that means I can now deploy this thing to fly and I can connect to it and then we should be able to see the stream uh yeah the stream live right let me just test one more thing like let let me just test that this thing is working here so I'm currently online oh also why doesn't the the loading thing ever St is it falling back to Long polling again no it doesn't Okay well I'm live I'm not live uh ABC one to3 I'm live I'm stopping I'm not live cool that works all right uh let's do this let's deploy this thing to fly so I'm just going to do fly launch and what do I want thanks Philipe how's your web RTC thing coming along you you also have to share your web RTC experiences with us because the next project will also involve Elixir web BC for like setting up a zoom clone basically I thought that would be a nice idea to to work on that next as a next project all right so we have um the twitch clone is a shared CPU I don't I don't need postgress but I guess my application needs postgress um yeah so I'm just going to add that with fly I don't want to fly can I I want to have super base so I'm going to do you want to tweak these settings yes I want to tweak these settings so let's tweak these settings uh I need to sign in one second boom let's see come on sign me in my internet is low isses an employing to fly at at the moment due to NS but otherwise the worst part is the JS okay I'm back what is NFS the National Institute for Fusion science is that what you meant it's in Sri Lanka why are you having problems with the National Institute for Fusion science in Sri Lanka actually this are fundamental studies membrane n ifs is that the native code implant integration are the N why why why you have problems with fly to to run this on fly okay well in our situation we want to set up the a network I'm also curious how we will actually expose that particular Port um here Services Port for each service section you fly for okay I I yeah we need to add this part here to add additional ports okay well we can do that here okay um yeah we going to have a shared CPU automated if we want to Super based obviously want to have like twitch clone DB running in Amsterdam no tigis no red is no Sentry sure and then we can see the exceptions uh confirm and boom now it's launching one of them can't load for some reason checking with the team to see if it did something wrong with the docker image deploy it okay is is it like rust or JavaScript or what kind of why do you need why do you need ni for the for real time oh but you're using real time right for your project that's what I would expect all right uh waiting for the launch dater you're about to create a second superbas database this is requires a paid plan please check to ensure that your plan supports this otherwise your launch May Fail I have the launch plan I believe so it should work boom no continue launching twitch clone yes all right it's running C lips oh yeah for about to see no no oh interesting I mean you you you you shouldn't be the first person to deploy web RC or Elixir web RC to super base to fly right yeah Google meets all right funny so then you can Implement your Google meat clone and then I I will Implement my Google meat clone and then we start a startup together okay so it's deploying it's deploying okay so we can actually have a look inside the tumml which we need to adapt eventually and in here we have our HP service VM yeah and we need to add the protocol and it would be rtmp so how do we do internal all right the example defines an HTTP handle on Port 80 an error so the handlers on arras of strings each string selecting a handle process to terminate the connection with at The Edge O that's going to be interesting whether we can terminate the rmp Handler on the edge here the HTTP Handler will accept HTP traffic and pass it onto the internal Port of the application which we Define in the services section above for the list of available handlers see the documentation all right where are the handlers yeah all right connection handlers TCP HTTP okay I'm going to I'm going to go to the toilet while this is deploying and then we hope that we can uh deploy the atmp thing that actually fly understands how to like send the atmp thing let's see e e e e all right we're back we are back and I believe our application is deployed now failed fun times that's always great bundle X couldn't load as dependency open SSL always open SSL it's always fun pkj config not found bundle needs pkj config to [Music] am I missing open SSL What's Happening Here you also got the advice [Music] to all right app Nexus ah here pkj config Let's see we probably need that one too so they are installing build Essentials git pkj config lip SSL okay anything else about pkj PKG PKG no okay let's try again deploy all right in the meantime we still need to figure out how to set up fly I mean Philip you oh yeah thanks you I um Philip you also had that situation where you needed to handle repb RTC the protocol right for fly like do you did you figure that out how to do that just let you see no no clue not yet well you will also have that issue then because yeah um set the handless config valid handless strings really only but in here for UDP applications let's use fly rtmp Handler deploying njx with rtmp all right so this person ask how to do this wait I need to deploy doer image for engine X and rmp module run I can deploy it but I'm not sure when strike yeah I mean what is this is is rtmp is that an HTTP part like I mean it's a protocol right but uh is it still running through HTTP you know that's why I'm a little how does it work well so rtmp is over TCP connection all right well then we just need to expose an a TCP port and then it should work sorry maybe that's a small but it says it right here rmp proper the plane protocol which works on the TCP and uses support 1935 yeah okay let's let's do that I mean I could also set up SSL but to be honest maybe not right now if we if we can get it to run then then that would be fine so also this person here they set up a service for the internal Port 1935 protocol TCP um Service Port 1935 so yeah that's I guess what we need to do this is always fun man yeah like the Builder also with fly all right there's another issue here failed to find vit de player oh yeah of course I also need to install npm I always forget that uh let's do the next maybe they have it here no they don't have npm install um let me just uh open a another fly tunnel that I have somewhere lying around CU we need to install um npm here for installing Vitz de player so yeah so we just need to do npm here basically and then behind the copy asset assets there copy asset assets we need to do um run npm install install prefix assets yeah let's do this one again all right cool but that means that in our thing here we should be able to expose the um the port 1935 and that would be a HTTP yeah convert TCP connection to http I guess yeah Services protocol TCP andless oh okay like this so we can do Services internal Port 5,000 protocol UDP in this case TCP and then I guess 5,000 will be exposed to the outside okay let's let's try this one out so if we go here we do Services internal Port 1935 protocol TCP um yeah I'm going to keep it at 5,2 though because like we could also set this one to 1935 but the problem is then I think for locally local computers you know they have like a a um was it the the ports are blocked in the between range is it from 1 to 1,000 or 1 to ,24 CU yeah um reserved Port range also on Linux yeah we want to have an ephemeral [Music] Port not Emeral what is okay the internal Port range is 0 to 1,00 and 23 so we should be able with 1935 as you can see here they're all reserved yeah also funny here 1935 here's the example for the fly tumml awesome thank you all right yeah here Services internal Port 18 85 here this one yeah cool that's what we need uh uh I'm just going to copy this and I'm going to put this on 1935 and 1935 What's Happening Here wait Services Services P why is it complaining yeah ECP 1935 okay well whatever it's uh formating weirdly but yeah so this way we should be able to expose our Port 1935 [Music] um now let's see okay so our our deploy is currently starting it's trying to migrate release command failed that's always fun ah well yeah we need to set a database URL why didn't yeah fly why didn't you set it for us no I don't know what the database Ur is um I mean it's now running on fly I'm going to check my fly maybe I can find it there like all the the pots that are running here my personal thing oh that's fun fly did not start the super base instant for us let's do this one again fly launch yes I would like to copy the configuration continue launching the app yeah all right in this situ we yeah I want to twg it because uh I want to use super base uh twitch clone DB and Sentry enabled twitch clone DB I'm just going to make this one word twitch clone together right confirm confirmed open the dashboard to check your plan yeah I'm just going to check the plan but it should be fine I mean I'm paying for super Bas I'm paying for fly oh fly extension super base dashboard if I'm not mistaken yeah I have opened my dashboard and now I don't see anything well you can see an old database that I had for my little game 2 million check boxes actually I could delete this one I'm just going to delete this this one cuz then I can create the the new one but to be honest let let me do this differently uh I have another like I actually have a paid account with super base and I usually create a database with them and then I just set the database UL fly extension okay fly extension super base dashboard no project found provision one with yeah I'm I'm all right uh Philip I'm going to I'm going to do this through my personal account so hang on a second what is the advantages super Bas F yeah no I'm uh I just have a couple of databases running with my other account and there I can just control it so then I have a database string I just copy the database string and I'm done somehow my Internet is slow today or everybody else is slow come on okay here we go um new project e all right creating a project um Now setting up the project Philip when are you when are you starting a a super base data center in Amsterdam because I always have to choose pyat or Frankfurt it's never Amsterdam maybe it's not coming at all I don't know I mean I'm on the launch plan so not sure whether you have like you know only the Enterprise version has access to Amsterdam or something maybe it's too expensive too all right I'm just waiting for uh super base to provision my thing yeah I I set the the blurry thing on because I have like some Secrets here so I'm just going to set up the database URL and then we can go back to the normal normal thing um Philip when I have the connection Pooler is a transaction or session I always forget that I think it's session right yeah sorry it's uh session yeah okay I session just give me two two seconds and then I have set up the data as URL but you know that that way actually I got you talking now I know that you're there so that's that's nice okay good your password boom adding the database URL I'm going to um delete my zshell history so that we don't accidentally expose any any Secrets here okay now we can go back there you go sorry for keeping you waiting so yeah I set up the uh the database URL so now we should be able to just run fly deploy and that will also run the migration against the newly created database hang on I just got to close the the tap and Firefox uh all right here we go so this is our newly created twitch clone DB oh look at this real time that sounds really interesting project status is yellow real time unable to connect Philip what's happening there real time all right our image is being pushed so yeah um so hopefully this will now work the deployment and once our thing is uh is running or maybe it's also my project I just created my project but for whatever reason uh it says project status oh no it's green okay no worries you can come back it's green you fixed it why all SS are restricted to organization members okay yeah anyway and yeah so we're going to start our Docker container here once that is running I can actually um configure restream to stream to our new endpoint there and we can even use f ofm for for just testing yeah and then once that is running so when once we have our our video stream running from or my local server to the website I can then configure restream and that's just going to automatically uh send everything that you're seeing here in OBS or like I'm seeing it in OBS you're seeing it on Twitch or YouTube or whatever and then you can see the same video uh on that website so right release command failed connection not available and request was dropped from Q after 3 seconds this means requests are coming in in your connection pool cannot serve them fast enough you can address this by why could not create schema ah okay yeah non-existing domain I know what it is every single time I'm running into this we have to go they should really ask that in the in the setup uh off fly like do you want IP version 6 to connect to your database no I no I don't want that and then they just go in here and set act the IPv6 to fult every single time I have to do this now again fly deployer yeah and it just I also have a video course about how to build your MVP with Elixir and I also said all all of what you're seeing right now I'm also doing in the video course and like every couple of months I have to come back and explain people again where that flag went because they you know move it in to different files and then it's like yeah you have to go in here and just disable the damn flag because other it will because fly postgress internally is using IP version six like if it's running inside your fly uh organization and then your app connects via IP version six to that uh container but if you connect to an outside uh database like you know what we do now with super base you need to disable the IP version six although yeah I can't show you the connec thing yet but I would also hope that super base eventually would allow version six connections and then this would not be an issue anymore yeah the things you learn from deploying a lot of apps anyway while we wait for this thing H you know we can just we can just set up our um our chat thing that should be a fast one uh and then do we want to persist chats ha you know what we do we will persist the chats in our game State uh stream State because then the the the messages will also dis disappear when I finish my live stream yeah they will be fine right we can just do that stream State and then we could ah we can just save it in here we can also save it in ads but whatever we can just do it here messages um and then I'm just going to do yeah and we can also limit our messages to a certain list like add message and then we just do this thing again all right add message yeah and in our index when we get the state yeah we're just going to we're just going [Music] to no messages uh we can make a stream out of that right but the problem here will be that we don't have an ID for the stream that's always something when you have this um we're not going to use yeah we should use a stream everybody uses a stream let's use a stream so we can create messages stream always forget that so the problem name items okay just messages and then we also need to Define how we create the Dom ID for each message um yeah stream save messages and you know what I'm just going to I'm just going to create a [Music] little like a little module here message and in here I'm going to make it a Def struct and it's going to get an ID uh it's going to get a username and it's going to get uh the content yeah and then whenever you add a message I want to have the username and the message and then well the content and then actually we create a message out of this and we going to generate a u ID username and content and then we're going to add it because then we yeah have an ID we have the username and we have a content all right uh so yeah in here then we have the messages and um so we need to create like a second thing and this is going to receive our messages so messages Phoenix update stream and then we can iterate our over the messages I'm make it a span um yeah yeah and also the ID should be right okay so now if I startop my server I have my little chat thing somewhere I'm just going to make that also white background [Music] rounded where is it ah well um where's our background where's our chat thing is it below messages well it's empty of course yeah okay um We Made It full Heights of course everything is a flex well I also use grid nowadays I learn about grid that's pretty cool yeah well yeah in here we want to have our messages and then we also want to have a quick form okay and all right now we going to have a two inputs thing we're going to have an input type uh with field form username and that's going to be a type text and well just like this and we're going to have the message wow look at that beautiful so here placeholder username and message if I could write placeholder correctly that would be great but this thing that shouldn't be a call it should just be a flex all right and then we got the the max isn't that beautiful I think this should be definitely VC funded I mean this is basic this is basically twitch no if you compare this not Twitter twitch I mean this is look look like if you compare these two I can't see any difference I mean this has some more information but who cares about that really right and this is just this is exactly what you need right this is like focused it's a very focused uh stream so yeah okay maybe we can make it a little bit prettier but only maybe so I'm going to do a border left uh white wait no okay maybe that isn't what we want what is this white thing here a that's our messages thing height full yeah it's dark mode exactly it's got build in Focus mode I mean what's the most important thing here it's it's me it is of course me so I want you to always look at me like look at look at what happen like there's so many things happening on Twitch you know for example you have like three times five times myself included is like there's so many things happening you can get crazy crazy doing all that kind of stuff like you want to focus on one thing only and that is the live stream isn't it so um yeah that's why this is this is this is high level design here this is functional design okay if somebody could tell me why the freaking hell my border isn't working ah there you go yeah and also always want to make everything full and minage screen so there you go also why the is this thing here I don't want to have a p i don't want to have this all right see now we're getting closer this is basically twitch I also don't want to have these things look it's it's getting closer it's getting closer and closer now this is our thing here we want to have uh justify between items stretch let show what you call this like I want to basically have this here wow so many things happening too this is my Flex box H full okay this is H4 okay so I want to have the [Music] form why isn't this thing very human design yes Ian you don't need much right I'm just going to add Peter and then hello well and of course I need to handle the Phoenix updates Phoenix submit um send okay maybe I also need a submit button why the heck doesn't enter I thought enter would would submit my my thing but it doesn't okay we need a button too here button post button all right good message username post all right cool so now we can handle that thing handle event send and then uh what's that message hey message it should be content username here so we have the message and in there we have our username content in our socket and um yeah also here so now we're going to do app stream State add message username content and we get a message back and then we're going to do a stream insert for messages and the message and we also want to have it at minus one so that would be in the end but we don't need minus one it's just going to append it all right so if I do Peter yeah also we should have a yeah username we want have data one p ignore thing like this because otherwise my one password is going to try to insert yeah there you go Peter message enter crash what's happening no function close matching message yeah typ poost it should be content not message boom all right uh Peter message enter exception what's happening today what expect the stream message to be a struct on map with ID God oh yeah I mean it's actually returning ah I'm a dummy this should only return a message and forget about the state here we go Peter content uh what does the data one p ignore so I have one p ignore is basically one password ignore and when you create an input field that has like a a name U username for example then one password will offer to fill out that field for you and you don't always want that like in this situation we don't want that so that's why you can use data onep ignore there's also other things like data last pass ignore you know data last pass ignore it's like a together you write it like this but I think they all pretty much um they look at this one password [Music] ignore and then then that's fine but we can also edit like it's it's all these password managers see here boom all righty um let's make this a little bit prettier so there you go isn't that amazing we got we got a message and it's big and that's what you need right it needs to be big so that people can read it because I need to actually explode my screen like I need to make everything really big so this also needs to be big so that people can actually read the screen right okay so nobody complain about my Ure skills I'm not that bad at it but also this should be flex and then I want to have a space y one and uh yeah that is much better should be Flex call there you go we don't need this stupid border thing there awesome now if I do Peter content to there you go we have a chat message and I don't even need to re re my my username I just you know keep it there okay but now uh let's maybe make this a little bit prettier just a little bit I know this is already really pretty but just a tiny bit PR all right now we have you know a bold username it's going to be super small and then we have a message here which should be like text XM text uh well whatever all right cool and we can also add a little bit of padding here so everybody knows well the button yeah there you go I mean this is this is Twitch look I can chat with myself of course now I need to also listen to other people chatting but uh yeah actually I I kind of want that so again here we're going to do Phoenix pups up broadcast stream State and now we can okay now we going to br broadcast on the stream State thing that's already what we um sign up for anyway right yeah stream State and we can handle a new handle info and we're going to receive a message and basically what we do is this one here stream insert okay so now if I do this again Peter and then I use poab actually there you go so now we add our messages through pops Saab so if I add if I create a second what's this if I create a second thing and I say Peter one Peter 2 and message to and I post you can see that in both chats it's appearing so if this isn't twitch I don't know what you want this is basically twitch right I mean this is this is good all right uh of course we want to have a little bit of um validation here so in my uh here I'm just going to just going to validate my validate message and I'm going to use a Ecto schema list change set so we have username um string and we have content string and then we have our defaults and they're empty and then we have ah I always mix this up with fields and then empty I believe Vector change that cast and we want to have the keys these are the attributes no wait these are the defaults yeah and we want to do hey dony that's twitch yeah right David you're a [Laughter] jokester yeah so we want to do validate required and we want to use username and content and then we want to do chain set validate length on uh well the username I'm going to have a Min of like three and a Max of I don't know 20 and we want to do the same for Content like minimum of three minimum of one for content if you want to send like a um smiley emoji and I don't know maximum 250 right uh um yeah and then we going to we're going to um apply apply action insert and that should give us here case oh jeez case Rel message message now we should either get a data and that way we can actually add the message or we get an error change set and then we can so if we get a change set we can [Music] assign a form was form no to form right two form yeah change set and then name message message all right no we should assign this thing okay I'm gonna going to create a little helper function assign form so and then change set and it's going to do assign socket form to form chain set yeah there you go and here we can just do sock chain set if you want to learn more about forms there is somebody who made a whole course about forms in live you and that person is me happy happy me so if you worry you know if you wonder hey what is this person doing here well this called a change a schema let's change set and it is uh part like I don't know five so here if you go to India courses which is my video course platform uh there is here building forms with live view that is me see also get good reviews a lot and um yeah section number second scheme let change set and then also we use them a lot later on so go ahead go the by the video course I heard people like it so yeah we also need to assign our change set yeah oh no damn it yeah this is actually our chain set and then we have a validate chain set [Music] um and that runs the message through the validate uh so the change set and then it um applies it so this is where we want to submit our [Music] form I'm just going to call this submit um and then we also want to have a no that's it we just want to have the chain set here with an empty chain set and then we can assign this to our socket so socket assign form change set and then it assigns the the state and the messages okay unknown field username given to cast hang on I did something wrong no I think the fields go here and this is where the defaults go I always I always forget this thing no okay uh cast data types I always forget it types data that's why this is empty and they are the [Music] defaults no this is defaults this is Fields all right that's already better um and obviously validate length this needs to be just a single not a list cannot generate name for change that where the data is not backed by a struct you must pass s yeah ah not the name uh this should be ass messages message there we go okay all righty so now if I add username but I don't add a message it's not doing anything assign yeah because now we need to use our form here instead all right now if I add Peter but no message it said can't be blank if I only add the message but not Peter it says it can't be blank if I eat both but then only like P should be at least three characters Peter Hello message good works all right time to deploy we have a chat system if I refresh the page well then okay the messages are actually upside down um so yeah we need to do that in our index or basically do the where's the stream there okay enom reverse there you go now it's nice top to bottom let let's add a very nice long message and then that's going to destroy our layout ah I don't know what the problem with this is like this this is basically twitch know like what happens if I if I put this on Twitch you know let's just copy paste there send a message look it doesn't it doesn't look that much worse I mean here it becomes more more important easy peasy but yeah so what we need to do is to have a Max width of like [Music] 40 um no not 40 maybe 80 H it's even too much 60 yeah and we want to have a rep rep uh uh truncate break words break normal grow what for the Chad yeah Break All In Flex you can have grow in the video window and gray zero in the chat yeah that's a good one so I'm going to do this like width 60 grow zero well actually I'm not going to have it here and I want to have the the other side also with 60 and in the middle I'm going to do grow yeah because now if we can make this red oh yeah now you see it's approximately the same yeah this is not very how you say responsive we can even make it responsive I mean no but I don't okay we can make it like slightly responsive just because it's quick so if I go like this this is my my mobile view so I want to have um basically I want to have hidden unless I am on a um what do you call that a tablet even the tablet I want that's only on large and here I want to have block so that already makes it bigger and um I want to have Flex call unless it is also large and then I want to flex row yeah but I also want to have Flex reverse so on on mobile devices like the video should be at the top no I'm doing something right uh wrong so I want to have um not flux reverse what is it called here if you don't have Ray cast that is something I can highly recommend it's my search thing in the middle I can just search for Tailwind classes so yeah it's Flex rad diverse reverse I'm going to make this Flex call Flex call reverse otherwise it is just Flex row so wait what's happening here I mean it should be call right like column because yeah now it's at the top okay my video is going to be at the top and also like it's going to be full but also want this thing this should be full full width why isn't this full width can you can you see that I'm a backend developer yeah this is full worth Max with 60 oh you are correct yeah you're right thank you kindly ah look at that beautiful again if I look at twitch and if I do I mean do they even have responsive layout they do not what is this we are so much better than twitch look they don't even have responsive layout unbelievable I mean everybody should switch to whatever I'm building here I would say uh let me just close these things all right um but I want to have a little bit of of padding on the side at least um yeah yeah that's already better and also here this could be text SM excess that doesn't make a difference where's my input here I that's one thing I don't like about the Tailwind um components that they they gave us because it's hard to overwrite the the classes here like they don't have an override I I always add like an override thing to it so here for example select text area this is the input and then they have a here SM text SM I don't I don't want that I want to overwrite I want to overwrite this yeah because this is this is bigger around that's yeah all right slightly better okay so um one last thing maybe here I can do a little there you go all right and now if I add [Music] more yeah it's actually going to the bottom H you know not too bad I guess is it now you can just scroll down then you see more messages um it's fine I mean I I would like it to be to scroll but I'm not sure whether I'm able to do that with CSS basically uh yeah what I want is I'm just I'm just going to make yeah I can I can do this here and the here I guess so the max height is the screen and then we have the Overflow y order yeah now I still I mean I have two two sroll things which also isn't great [Music] I mean that's a CSS thing where I say well you know my my text thing should not be higher than my screen wait what's happening here now that's all right here it grows with the screen okay but then I'm also going to set this one it's all right it's all right it's good enough right it's good enough like nobody's going to look at this on their on their uh mobile I mean even twitch doesn't have mobile so whatever yeah um so we can actually set this to 80 no not 80 60 70 there you go and then on this is only large and then otherwise we have Max height of 50 be like please don't take this as my like I'm I think I'm usually better on CSS at least I I hope so but today like I I just try to hack this thing together now you know um I I don't care about whether it's super responsive or not like you can see the messages you can post messages so you know this is not the level of CSS I know and I mean I I built something pretty nice I think with India coures you know it it's pretty it has like uh I don't know everything is nice the The View thing is nice if you if you look at it as a as a student you know I think it's slightly better and it's not it's not terrible CSS either I I try to keep it minimal you know but for now whatever just you know make it work kind of so yeah okay you know what I'm just going to make this dark as well and then I promise you we will yeah that's already better right that's not so terrible all right Philip have a good weekend all right almost there in terms of um making this thing pretty wait I now have two scroll bars how does this happen ah don't worry but thanks for being here anyway much appreciated I'm just trying to not make this look terrible okay that's already better and now in here I need to um make this grow a bit more yeah oh wait somewhere there's a max weight max height there you go that's better that's what I wanted okay all righty so that's better right now we have a beautiful a beautiful screen like a message thing screen I mean it's basically twitch basically twitch there you go you can you know add messages scroll through them um cool good enough username message good enough all right cool then I would say we can uh actually I'm going to move this here to make it even prettier yeah ah it's not that pretty let's move this back okay cool so I would say let's see this was deployed so we actually already have a running uh twitch like a server here let's see it's probably also turned down um like turned off I I never like that I mean on standard that they have like uh they turn it off but I I want to have here Max minimum machines running one because now it's actually starting my my machine or is it maybe it's also crashing no oops Colonel pit terminated lip R SRT native oh that's I think what Philipe had the same issue no yeah now it would be great if Philip was there because like we have that issue where we deploy our application and there are some NS running um and I think they're they're crashing no damn it all right we had we had such a nice nice chat system here I just want to deploy it um yeah I'm just going to have a look so Philip he send also a fly a Docker here Docker file and a fly tml and Bas probably the docker file um this might have some pointers at why the ni isn't working here's some stuff let's let's check the the things they install here with our own DOA file so over here oh but they're the same damn it Nexus I mean they use the the book worm so we can also use Bookworm maybe instead because bull's eye is always a little bit smaller and we need to find Docker Hub hey har is um thanks for joining so what we have like we deployed our application to fly currently we have an issue with the nif that is um supporting our our membrane rtmp server yeah so our rtmp server is running some C and that ni for whatever reason is breaking and that's a problem that also Philipe had another friend of mine uh so now we're trying to figure out how to solve that so that our server is actually starting and then once the starts like we have an rtmp server running uh and then I'm trying to connect from my local machine to that and just push some some uh uh video that way but while we while we were waiting for the deployment we build our little chat system here where you can you know add a username message and just ch send a message basically so yeah uh currently I'm trying to figure out how to get the nif running and first I need to find the proper Docker container here that we can run so it's 11 173 earling 271 um book room wait hello earling Debian yeah so this is this is what we [Music] want okay so this is now another Docker container so we like we have this Docker file from another project from the web RC Project um so now I'm just copy pasting everything that they have and trying to make it work we had three hours already Jesus today's a long day isn't it but I kind of want to get this running I mean we're so close we're so close now this doesn't look too crazy all right let's try this one again let's do a fly deploy yeah otherwise I might also call it a day soon oh yeah well now your message was there I saw I saw like a smiley thing yeah um yeah otherwise you know we can also take a break here come back on Monday see whether we can make it work until then maybe also Philip had some time to play one with his project and can give us some point as how to fix it yeah uh yeah no worries hang on my my twitch uh well I can't share the I can't like copy paste into this chat thing but if you go to Twitch and you look for PJ or Rick you will find me here PJ I wish I could paste into this but it's just twitch.tv PJ there you go all right now we're deploying our application here but we're very close very close we have a chat system yeah so one other thing I wanted to set up also eventually is whisper so we have a whisper model running in the background that transcribes our uh yeah well the basically the live stream right so that we can see it happening live um I'm not sure whether I will get into that though I don't know it's already a big project what do you think do you want to do you want to see whisper at work do you w to spend like potentially a day or two or three uh setting up whisper um all right oh cool thanks lip srtp def Let's uh let's check what is this lip srtp to Def yeah let's see so I I have a a Docker file here um thanks Chad MX for that tip I have a Docker file here from um another project that uses web RTC it's oh it's for RTP needed for okay uh yeah I see okay let's hang on I'm just going to try to deploy this thing and then once that is through and it doesn't start then I'm going to add that one um also interesting like do they have membrane do they have like a Docker fell maybe so this is a Docker file here yeah but that's something else okay awesome will be fun and with a new whisper model could be very fast yeah um I'm thinking the same I mean it would be nice so I I think what we could do H but there there a couple of problems what we needed to do so if we use boom box uh for I mean what I would like to do is to set up a second kind of stream and then it takes like an input which is our rtmp and it creates an output and as an output I would like to well ideally I would like to have audio out but unfortunately I'm not sure how we could do that I mean we we could have a stream here I think that that's what something I would try to do like have a stream and then see what we receive as a stream because maybe it's like split into two and one of them is the video and the other one is the audio or something um I'm not sure what they what they return here is a stream here is a stream or numerable um and then let's see here maybe we can find something because I only need the audio and once I have the Audio I can actually uh send it to whisper in chunks I mean for that maybe also the stream would be ideal because then uh we can just send chunks of the stream to whisper and then receive the transcript back yeah that's the idea um let's see see not hot dog hls MP4 yeah because I don't I don't want to have an mp4 because then we need to demox it again so Dem maxing is splitting the audio from the video so that would actually be harder with uh dmax record rep RTC to MP4 yeah reads speech audio from MP4 chunk by chunk generate transcription look at that they even have an example of using whisper ah I mean come on if we already have an example like that right because yeah they use boom box and then they have an input and I think we could just set up another yeah look at this we could yeah set up a second input hopefully I don't know uh from uh from the rtmp thing I'm not sure how it is with like handling the same packages maybe only one of them receives the packages and the other stream doesn't receive any packages we we have to look into this how we can set that up uh but ideally yeah otherwise we we just I don't know find somehow the MP4 and then yeah we can have an output stream sorry maybe this is too small uh output stream which has video faults audio binary audio rate 16k uh 16,000 Hertz one channel and then Auto from it and then we can actually stream that right into NX and uh yeah use speech to text whisper and then we just need to give it a GPU and we're good yeah so this is cool I mean the only thing that I see here like that we need to check out is whether we can have boom box running twice on the same input no maybe that's not possible let's see okay so this deployed let's see whether we have any errors fatal no config space yeah there was something a kernel shutdown what was it recently it might now here 1624 this is when we started the new one so maybe it's running let's see was it twitch clone fly def oh it's running it works H all right yeah okay but before you go there uh I I also need to set up wait hang on I got to I got to pixelate my screen again don't you know it's just pixelated I'm still here don't worry because I need to set um I need to set the the stream key right otherwise people can just uh I can just add something okay I'm just deploying now but that's already cool so we got our our system running I mean you know people can just abuse a message system please don't but I mean otherwise it's running in memory so if I just restart the actually that's one thing right if I restart the machine all the chat is gone maybe we should have saved it to the database but ah I'm just never going to restart the application while I'm doing a live stream easy as P okay and um okay so let me unpixelate again there we go so now we still have our application running here yeah and the the messages are gone right uh that kind of sucks though do you think we should store them in the database so that we I mean ideally we would have a no downtime deployment but I'm not sure how to do that with fly I've never done that before yeah maybe it's easier if we just store them in database and then we can retrieve them between I mean we have a database so yeah let's just it's it's like one uh one command so mix Phoenix gen context messages message messages username and uh content boom easy peasy lemon squeezy migrate and now in our index live we um get the messages but only only if reconnected otherwise it's an empty thing okay messages and the stream State we can delete our message all right um so basically in our live view here we need to when we create a new message there we do app messages create message with the dater yeah and then for message yeah we can now also move these validations to the message so we can actually remove the chain set oops yeah all right I think we start our server um ah change message yeah all right so yeah now we have our live view running and we store the message in the database so if I not do message and Peter need to rad messages after submit um wait hang on there was an error well no I I don't need to reload all the messages so what I'm relying on is basically when we create a message here like yeah we would we get the message back but I'm waiting for the for the pops up broadcast basically it's it's not ideal like ideally you would insert the message after you submit it here um yeah we can actually do that we can that that's n I'm not going to do it it's easier this way so uh what you could do usually is like you create the message on the database and you you get the message back and then you insert it directly into your stream like in this live view and all the other live views they get notified using pops up and you could do that easily in the messages if we would uh rewrite the broadcast with a broadcast from because then you're not sending a message to your own process you're just sending them to all the other ones and because our live view is executing this function like the the live view would not receive that broadcast right this way we could like in the live view add the message immediately after we edit it and then like we would not get the broadcast in this situation because we use broadcast not broadcast from um our life view would also get that message so that's why I I just it's it's easier to just like you know wait for the broadcast to go to the live you um there might be situations where you know messages are out of order but I mean it's it's over complicated but this is just easier right so I'm going to do that however there was a here change message um what is the issue I don't know what is the issue wait there was an issue let me oh well that worked okay and now if I refresh yeah it's good and yeah we don't even need to order the messages by inserted ad because um they are by default ordered by the ID and in our situation you know all the messages they um like we just add them yeah you know what I mean like yeah they get they get added in sequence in order already so we don't need to order them by inserted ad anyway so yeah now I can actually turn off my server and restart it again and I'm not losing my message State cool all right let me deploy this one and then we can try out our rtmp server all right so how's the uh where the twitch clone yeah there no messages what's Happening Here on Twitter lots of notifications I also asked the membrane people earlier about our issue yeah here look hi there I guess it should be automatically terminated after a timeout but that could be useful too please open an issue all right because I I asked them like can we you know in the handle new client call back if we could say hey don't accept this connection uh and Matos he's really really use he's really nice and responsive on this so that's great all right I will do that later oh cool Jack my dat is even following me cool uh let's see how's the deploy going still pushing yeah but then after we deploy this then I would like to try to send information here and then to see oh look hey Jet oh yeah sorry uh you can this is the URL um I I still can't post in here I'm not sure why twitch minus- clone fly def this one yeah I can also put it here and you can see easily I'm going to wait until the deploy is done uh we could also use presents you know like let's let's just add presents while the deploy is running because I would like to see how many people are watching right that's something we want to watch so and I always every single time I forget the API of Phoenix PR but luckily the documentations are here so yeah we need to have a presence [Music] somewhere pres it's in the app web folder so I should move it there too and it's using psub and it's using App okay now the next thing is to start it in our application I can do that uh stream stage app web presents then once added presents can be tracked in your channel after joining yeah so this is my wait how's this time with live view again yeah using present client they have it with Phoenix Life View setting up [Music] channel oh wait yeah um after Jour right so we got presence track what's happening here next we create a channel that will communicate presences over after user joins we can push the list of presences down the channel and then track the connection we also provide a map of additional informations to track n making it safe usage with live view there you go all right the final thing to add is a handle meta's callback this call updates the state that we keep track in presence based on the user lease and joins and this complicated isn't there okay so we can just copy paste this stuff Jesus in here no but proxy topic ah this seems to be too difficult let's let's find I think this one full stack Phoenix they have a better tutorial [Music] here yeah because they have like presence track and subscribe and then yeah this is all okay this is this is what we want though so we actually want to move this like we want to move this to presence like join presence and this is like a topic so stream audience [Music] um and we don't have a username though so I'm just going to make this a uu ID present trick oh yeah okay and my pops up app pops up so wherever this is yeah and then just delete all this so this is a helpful function we can call to join and then what is this tracking again but yeah we're tracking and this is some matter information okay all right and then we can also have a list function material presence andle join oh freaking hell I just want to have a number of how many people join okay let's maybe not put this here okay let's do this here join prons and pops up all right so we got our join function when it's connected and then we have handled to handle joins call back so yeah so when we join when we start our server we do we just fetch all the how many people are in there yeah okay H info should go together I can do that it's always every time I use presents like it's it's it's a great framework but it's very low level right shouldn't be in the live view yes sorry I moved it there I'm sorry I was a little not observing um every time I use presents I feel like it should be easier but I understand that the underlying Library it needs to be complicated or like configurable enough so that you can actually do really the things you need with it but but I always feel like there should be an easy just thing where you just like join and then list you know and like track or whatever like so just like two or three uh functions where you can actually see where you can just you know easily call into these things okay um so what's actually happening here we add to the users yeah we just have a user assign [Music] here and uh yeah again we can just when we are connected we can also join presence all right so what happens now I got to start my application all right so I'm starting and I also want to add like a counter right so maybe above this beautiful little [Music] form here like user count but I think yeah I have like two parts here reduce drawing meter yeah I don't want to add all these uses I don't care about the I just want to have a delete yeah it shouldn't be a map so I just want to count how many joins and leaves there are so I do that here basically the oh for sake so when I do the join presence there I track stuff okay and then I get the messages that presents diff oh wait yeah first I get a list present so that actually gives me this broadcast no handle joins this is the first thing okay these are all the users that are there I would I just want [Music] to uh okay so I'm not going to do any of this I'm just going to do assign user count and then a length of that and I'm not going to okay so yeah this is how it starts but basically um what I first need is like a sorry like in the in the beginning when the live view starts right I need to have like a zero count basically so I'm at zero so I'm just going to do this and then I'm going to add how many joints there were and when I do leaves I'm going to do the same but I'm just going to subtract the amount of leaves yeah and that way I could also use update but I'm not sure update it doesn't have um like it expects the the key already to be set yeah one to two ah thank you very much assigns current user count user count and then I assign the user account and I add or remove the joints okay yeah and uh so that's what I do when I start the live view and whenever a diff comes in then I you know I add them too all right yeah and I need to also use user count here in my uh here user count not an argument one two three it's not a list what the joins okay first argument is not a list of length I guess yeah what what are we putting in there what are these joins us account not found in yeah okay oh it's just it's an empty okay so it's not length it is Map size because the joints is not a list it is a map all right now we have our us count two interesting yeah because I have a a second window somewhere or am i counting myself twice wait do I have a second window yeah here no I have so many Firefox windows open but that's it is the only this is my only one okay now I have user count one interesting ah one two I'm counting myself twice but not always um but what happens if I move away and then I come here use account two that's weird I mean I join do I have to filter myself out I think I have to filter myself out right let's see what happens here in the diff inspect the joints maybe yeah thank you doing that here okay well now is user count one now it's two so now here I I think that is myself yeah so I yeah let let me let me put this here in the handle joints okay yeah so there there is the same ID twice yeah I I think I just need to filter out myself there right because I'm I don't know I'm still here I'm refreshing maybe if I heart refresh no still like oh that might be with a mounted thing right because I no why does it happen twice I mean I run join presence only after after the mounted [Music] thing but I run handle joints on the mount and on the remount right I only when it's connected oh as gu you join and then is broadcast everyone including yourself that that could be actually that could be um you know what I'm not I'm not going to do this no I should be doing this handle drwings I'm G to I'm going to move this [Music] to I'm going to do run this only if I'm connected let's see what happens in that situation What's Happening Here Mis much and else to if else and ah I'm missing a thing uh and then H yeah let's see what happens now user account can't be found yeah and I'm going [Music] to I'm going to assign socket user count zero yeah now it's still 02 oh joints can be of the status [Music] matter no no there's no status in here uh what we can yeah what we can do is just ignore ourselves so [Music] yeah so I'm going to move this I'm going to move this back here and then I'm going to filter myself out from uh from the joints and I'm going to assign yeah but I want to assign it oh damn it I want to assign it on the mount join presence well I'm gonna I'm going to try this so all right so I'm going to do this so when I join I'm going to join with a preset uu ID okay and also I'm going to assign a user account ah of one we because you know I'm already there all right folks I got to before we continue here I'm just going to do go to the toilet real quick and then yeah and then here we can filter ourselves out depending on the The UU ID if we have it but we like my problem here is like if we Mount then we generate a uu ID and then we come back and then we remount The UU ID might be gone so we need to figure something out there I'm going to be back in two seconds e e all right I'm back and also just a little hats up we are closing in on the four hours of live streaming so I think uh at the 4H hour mark I'm going to I'm going to call it a day and go into my weekend and then on Monday we can continue with this I mean we still we still have to figure out the the actual streaming part but I think the application's already deployed I mean there was an error that I saw earlier but uh it's still running okay Jet and Bob already answered something hello there you go um yeah but definitely we make good progress we have the chat running H that that's also interesting if if you go if you go to the What's Happening Here If you go to the website and you refresh like sometimes you only see one message and sometimes you see four messages why is that look like now I see only one message I think is it I don't know I think my deploy broke and this is still the old version and I have two machines running and they have separate state so I'm like connecting to one of two of them why would this be this is so weird oh that's funny you know the the miracle of distributed computing all right now I see Dave and Dave is also on the second machine but not on the first machine what's happening oh wait yeah so I because the machines are actually connected so fly when you deploy the machines they cluster them so if I run Phoenix uh broadcast it actually goes to all machines that's why I saw Dave's message but it's actually on the second machine and the Emoji test pass as well so now I see Dave again but I think he's connected to the other machine so if I refresh like now now I'm on the second machine Jesus yeah we really need to I think the deploy didn't go through that's why our data it's not actually stored in the database right now it's just two machines with two different states there you go all right but let's finish this first so that we actually have the present thing running and then sorry then I have to remove all the messages and and start actually the use the the database all right um so what I wanted to do here yeah so um what does does our socket have any reference any running reference that we could use um B yeah I'm just going to sign this thing wait uh ah I think we can also do a sign new I'm not sure I don't think the socket no the socket is not contained between refreshes right like if we mount it and then we remount it then it's two different socket uh instances but I'm just curious does the socket have something that like um a unique ID that it keeps between remounts well it has an ID is it staying the same uh what am I doing here well this this is the ID to ah yeah okay no it's a different ID damn it so there's no way for us to yeah you know what I'm just going to move the whole like joining showing how many users are there I'm going to move that to the mounted State not to the unmounted state so then we don't need to worry about it in the unmounted state so I'm just going to yeah so if we connect it all right I'm just going to do aign soer user count one basically because you know I'm currently connected um yeah and then I'm going to and when we are connected I'm going to join the presence and I'm going to assign as a uu ID whatever we return from join presence which is down here and this is going to be a random uu [Music] ID all right and I'm going to return it so this way yeah this way so and then handle joins I'm going to I'm going to run here yeah so let's see yeah now we only get one joint it's still user count to well we haven't you know we're not filtering out ourselves yet and I'm going to do that not in the I'm going to do that in the broadcast so enum filter I actually reject what what's your what's your thinking about enom reject versus filter like filter is an OP like you can also do it all with Filter I just yeah reject never I never understand exactly how reject it's kind of like this unless thing which also they're going to remove now in 118 Elixir 118 so I kind of I kind of understand like okay with Filter you know I'm going to return only those that that are true but then with reject it's kind of like a double negative logic like I'm rejecting ones for which it's true so I'm returning only those which are false you know it's a little so I I rather like to use filter instead of reject because it's always like okay if it's true then it's return it's pretty pretty simple it's like not if it's F it's return like anyway [Music] um the unless mro will be removed that is true in 118 well it will be dep deprecated but unless will be deprecated in 118 and probably removed in the future however there will be a migration command that you can run it's going to be mixed format D- migrate and that's going to move like uh it's going to rewrite all unlesss to the if form I know it's from Ruby it's it's you should listen to the latest Elixir thinking Elixir podcast uh because they talk about that and they also say well yeah some people will you know cry about it and I understand that um but for many others it I don't know actually why they remove it like you know it might just be a purpose like it's a way of of reducing the the language API a little yeah you're going to cry I'm sorry about that uh yeah I I don't know maybe you know start a petition and say don't remove unless um yeah I'm sorry I don't I never I never use unless and I only use unless if I want to throw exception you know and I say unless this is true then throw an exception but otherwise I always use if yeah but okay anyway we want to filter ID unequal socket assigns U ID okay and then we only use those joints here all right oh EXP back the map got ah it should be a map right [Music] um can we just make this a new map yeah all right yeah I think that works now okay so yeah now I can refresh as often as I want use account is one that is good because we we only we only get this uu ID when we run the initial um handle joints this one here ah you know what we could also run the handle joints before we do the joint presence of course why didn't we do that we made it so hard on ourselves we do the join presence before we do the handle join and then we yeah and then we run the handle join which returns us and then we receive the broadcast because something changed which also includes us that's the issue here we made it so hard on ourselves yeah okay uh I'm just gonna I'm just going to remove I'm just going to rewrite this because it it it it's going to make it much easier so we do um hand one well yeah actually then we don't need to to run that thing we don't need to run handle joints in the beginning at all like because so in the initial yeah we join then we run the handle joints and then because we joined we actually get a a call back um so hang on yeah I'm just I'm just gonna do it I'm going to do like this so if it's connected we do hand I'm not going to do the the list I'm only going to wait for the broadcast here and I'm just going to use diff joins right now now our issue is back why is that damn it but I thought so wait where's our join presence thing wait oh I think yeah yeah yeah I think I think we because we received the message twice I guess once for the unmounted and once for the mounted no whatever how is this possible yeah what also could happen is no so we run join presence only when we're mounted so we can forget about the unmounted version and then we join and we receive like one message or two messages ah I'm a dummy because I set this to zero and then when we actually get the message yeah there you go because my my initial my initial value for this was one and then later on when we uh actually receive the broadcast that somebody joined we take the old value and add one so that makes two right but we only like that's why we need to start at zero anyway long story short now it works everything's fine we don't need the U ID uh boom yeah join presence is right [Music] and can just get rid of this thing we don't care about the uuid anymore I'm just thinking I think I want to subscribe to the pops up before I do the track just in case that there's an issue with with messaging yeah you know like we track and that's going to create this broadcast the pops up broadcast and because I think the subscribers fast enough to you know go in before the the broadcast that's why we received the message but I think just to be sure I want to turn these two around okay all right Jesus so now if I start a second window what happens user count two user count one that sucks oh my okay we need we need the list thing Jesus we need the Lis thing because yeah the diff is only gon it's not going to give us the absolutes why is it not giving us the absolutes like here event payload topic and the diff What's the diff does it also give us a it's just a diff yeah leaves and Joints okay okay okay so we need we need the list um and then we listen only to the diff so we man we need the whole uid thing now don't we Jesus Christ yeah you know what I'm just the uid thing worked I think it worked and and that is fine I'm just GNA I'm just going to do that so what we wanted to do is we wanted to list we wanted to give ourselves a uuid okay yeah I'm gonna do this I'm going to assign myself a uu [Music] ID and um actor all right and then in here I'm going to pass it along so that we actually subscribe with our own with The UU ID here we go okay now we're tracking ourselves when we join and in here I'm going to do handle joins and uh what's that app web presence list for presents and joins okay yeah and now we have that issue that if I join there are three and there are three okay so now I need in handle joints I need to um yeah I need to filter the joins and I'm going to do if the ID is unequal to ass science uid and then I'm going to do that create a new map out of that all right so let's see what happens now user count one user count one still doesn't work properly why it should be two and I'm kind of getting tired of this no I mean let's let's print out here the the the joints man this is way too complicated yeah so I have two and then I have one wait in my situation here now I need to add the one again again right because I'm filtering out myself that's why it's now two and if I start a new one it's three see now we have it like I have a third one here I have three everywhere three three three if I close this one two one it wasn't that hard was it two one one see all right problem solved Let's uh Delete the IR inspect and deploy the whole thing Jesus Man four hours eh I feel it but it was a very productive day I think we did a lot of things we fixed our player we added the chat thing we deployed it to fly um what else yeah we even we even fixed the thing where like if a stream starts we show it you know like we show in the in the window that the live stream started uh we hide it when it stops we block anybody who doesn't have the secret stream key which also is going to be fun actually I have to put that somewhere in my n feere otherwise you will see the stream key if I run the the FFM pack command yeah it's not easy to do live streaming a lot of Secrets and then it's also recorded you know people can rewatch it and stuff so you have to have to be super careful anyway do you have any interesting projects you're working on the weekend do you have any side projects you're working on like if you share it if you share the link then um I'm happy to to look at them all right it's being deployed migration is running what we could also do is when the stream stops that we delete all the messages because you know then I don't have to keep million messages on the database that's okay for now let's see who's still there couple people on Twitch let's do a around if you if you listen to this then send a message please in the in the chat so that I see that you're still there would be interesting because you know we don't have presence it's not it's not as like twitch doesn't have that well actually twitch tells you how many people are currently watching but can you trust that I mean they don't even have responsive um responsive UI so all right Jed is still there thank you release command failed all right what's happening here um info could not create schema migrations table the error usually happens to do the following the database does not exist the schem of migrations table which act uses from my what oh man why all migrations are breaking why is that the database does not exist but the database does exist let's have a look at the database one second yeah that's a database security issues yeah whatever they always give you the the row the ls row level security where the table well there's schema migrations is there let's see my connection thing I mean you don't need my you don't know my password so session oh I think I I selected the wrong uh mode here I think I selected transaction not session yeah let me try that again I need to set up the database URL but the migration work previously right so why doesn't it work now weird yeah let me just try to set the database URL again hang on one second I got to got to blur out my screen here because I'm going [Music] to set database URL I'm going to look up the password there you [Music] go I'm going to add it and post okay that's it's annoying that our biggest problem now is super base actually okay the machine is updating I'm going to be back in one second with the with the pixelation here was waiting for the app to finish like the update of the machine okay that is correct okay on pixel8 there you go all right now let's try this thing again ah damn it I exposed my database URL to your well all right sorry uh have to change change the [Music] password be nice if Philip was here then he could tell me how to change CH now reset database password okay okay reset password now I got to do the whole thing again anyway I mean for today I would just like to deploy the whole thing um and then you know be able to just have some um some messages there you know so they actually they get persisted and all and then I think we call it a day because then we have the presence running we have the chat system running we have our application deployed like the technically the rtmp server is there and we can connect to it and send some live stream um but yeah only technically so let's see how that works yeah I'm also very smart forgot my stream key hang on I'm just going to couple of Secrets okay man I'm getting tired all right hang on one one last thing okay good now we can go back here we go I am back um so I updated the database URL I also reset the password there for the database so if you saw the database uh the password earlier on the stream it's not no longer working and uh now we're going to try to deploy the the machine again the problem here was the migration for whatever reason it couldn't run the migration process properly um so I also changed over to the session mode now like super base has two connection um a damn it release command failed why the is this happening I'm getting really tired of this connection error um could not create schema migration table where it's already there okay I think I know what might be happening the problem might be that we already ran a migration earlier and now it like stopped working hang on I think we just got to we just got to reset our our super base database and okay here there you go so what we can do is database if we go to the database I'm just going to reset it database [Music] management okay no infrastructure database like there's already schem of migrations table you know that's what I meant here delete table we can just do that okay there we go so now it's an empty database okay now let's deploy again and hope that it's smart enough maybe there was going something going wrong with the deployment earlier and then it was actually creating the migration but for whatever reason it didn't you know note that somewhere so now let's see where that works yeah but otherwise I think also we have like 4 hours and 15 minutes of streaming it might be a good time to slowly come to an end but I would like this to get like I would like to get this out of the door that would be nice destroyed failed ah me why could not create gem on migration table check it locks here are the M grator yeah that's the message we received database does not exist SC mations tables which actually uses for managing was defined by another Library there's a deadlock while migrating uh yeah I mean do we need to run M uh create first but the database should already be there because here they say to fix the issue run M mix actor create for the desired mix en uh I mean we could we could do that I always forget how that goes yeah okay so if we go in here and then we do mix acto create commanded found mix is not uh because it's part of the releases but there is the my greater thing yeah mix app release migrate my great run never mind I will figure that out I will figure that out another day not today I think we already spent enough time on this I'm getting tired and uh you know we also want to keep some stuff for next week so I think I will just wrap up here it's a Pity that the database is the issue but I don't know I don't know like whenever I set something up on fly it's a 50/50 chance that it doesn't work um and I'm not sure whose fault it is I don't think it's always fly's fault to be honest we also added our own database here we deployed and all that kind of stuff we launched twice because the first time it didn't take um it's all right like I'm not putting blame on anybody it's just kind of frustrating that like you know a single command doesn't always work yeah but it's all right I'm going to figure this out and then Monday we can finally con uh continue yeah I was very productive thank you Jad uh we have the chat system we got presents we have our application running in production um it was my fault all right I'm just gonna put all the blame on you it's your fault thank you for uh you know being the the black sheep here no but I think it's it's cool like uh yeah I will figure that out it's probably just like you know resetting something and then it works so um I mean I always yeah the IP version six is f so that actually should work I think I just need to run uh mix XO create or something yeah anyway I'll figure that out and then Monday uh a little bit later than today like 400 P p.m. 5:00 P p.m. Amsterdam time I'm going to continue with this project I'm G to hopefully by then I have this thing deployed so then the next step would be to actually push some rtmp data to the server so to actually start a live stream on this on the on the website right and uh yeah that will be the cool Next Step I'm going to do that with FFM at first and then once it works I'm going to continue my restream thing and I'm going to stream from OBS to restream and then restream to our server yeah I mean by that point we basically have a twitch clone right 100% feature complete uh the only thing we need is VC funding so if you have some rich friends with much money that want to invest into a shitty product builds uh in a shitty way very quickly but has zero potential to make money in the future let me know you know I I would be willing to talk to them but until then I thank you I appreciate a lot that you joined the stream I thank you for the support mentally and with tips as well and I yeah I appreciate you all so have a great weekend enjoy your the rest of the day and I will see you again on Monday right that sounds more promising than half of the VC startups yeah maybe like if you look at this y combinator thing where they just forked a was the cursor your AI and renamed to PE Ai and then they got into white kulminator yeah it's just you know that's another thing I tweeted today that expertise and years of experience that don't always go hand in hand so I I've met people who work for like two three years as a software developer and they were much more capable than somebody who's work who worked for eight years just because you know these people were like trying out things reading books experimenting learning every single minute of every day and then you have people with like eight years of experience and they basically they basically stop learning after half a year or one year you know um so that was my take earlier today expertise and of experience don't always go hand in hand and my other take is also that uh um yeah if you have a lot of money doesn't mean that you're smart like these two things also don't always go hand in hand although it seems to people like that so yeah anyway uh thanks for everything I hope you had a great time join me next time uh subscribe to me here on Twitch or wherever you are YouTube you know and then you will get notified but I'm also going to uh tweet about it and put it on Blue Sky
Video description
Let's code a Twitch Clone in Elixir together using Membrane, Boombox, and LiveView