From 07ffb1b75f5c76299b22c4e15e479502556c89db Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Mon, 15 Dec 2025 16:49:48 +0100 Subject: [PATCH] feat: Introduce backend server with live TV proxy, VOD HLS transcoding, and IPTV streaming settings UI. --- Dockerfile | 12 ++++++-- bin/api/streaming_handler.dart | 16 +++++++--- bin/pubspec.yaml | 2 ++ bin/server.dart | 29 ++++++------------ build_log.txt | Bin 0 -> 68014 bytes build_log_2.txt | Bin 0 -> 82154 bytes .../iptv/providers/settings_provider.dart | 1 - .../iptv/widgets/streaming_settings_tab.dart | 15 +-------- 8 files changed, 32 insertions(+), 43 deletions(-) create mode 100644 build_log.txt create mode 100644 build_log_2.txt diff --git a/Dockerfile b/Dockerfile index 322bdce..af954ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,7 +54,13 @@ RUN apt-get update && apt-get install -y sqlite3 libsqlite3-dev ffmpeg && rm -rf # Create directory for HLS stream output RUN mkdir -p /tmp/streams && chmod 777 /tmp/streams -# Copy entire bin directory (API, database, etc.) +# Copy pubspec.yaml (required for dependencies) +COPY pubspec.yaml ./ + +# Copy lib directory (required for shared models) +COPY lib/ ./lib/ + +# Copy bin directory COPY bin/ ./bin/ # Get dependencies @@ -67,5 +73,5 @@ COPY --from=builder /app/build/web /app/web EXPOSE 8089 # Serve web application with API proxy -WORKDIR /app/bin -CMD ["dart", "run", "server.dart", "--port", "8089", "--path", "/app/web"] +WORKDIR /app +CMD ["dart", "run", "bin/server.dart", "--port", "8089", "--path", "/app/web"] diff --git a/bin/api/streaming_handler.dart b/bin/api/streaming_handler.dart index 9fe4325..c958eb1 100644 --- a/bin/api/streaming_handler.dart +++ b/bin/api/streaming_handler.dart @@ -34,13 +34,19 @@ PlaylistConfig? _getCurrentPlaylist(Request request) { Handler createLiveStreamHandler(Future Function(Request) getPlaylist) { final router = Router(); - // Route: /api/live/{streamId}.ts - router.get('/.ts', (Request request, String streamId) async { - final playlist = await getPlaylist(request); - if (playlist == null) { - return Response.internalServerError(body: 'No playlist configured'); + // Route: /api/live/{streamId} (Catch all pattern to debug) + router.get('/', (Request request, String streamId) async { + print('[Live] Incoming request for streamId: $streamId'); + + // Remove .ts extension if present + if (streamId.endsWith('.ts')) { + streamId = streamId.substring(0, streamId.length - 3); } + final playlist = await getPlaylist(request); + + // ... existing logic ... + final targetUrl = Uri.parse('${playlist.dns}/live/${playlist.username}/${playlist.password}/$streamId.ts'); print('[Live] Proxying: $targetUrl'); diff --git a/bin/pubspec.yaml b/bin/pubspec.yaml index ad951e4..cd99d09 100644 --- a/bin/pubspec.yaml +++ b/bin/pubspec.yaml @@ -15,3 +15,5 @@ dependencies: sqlite3: ^2.4.0 crypto: ^3.0.3 uuid: ^4.3.3 + hive: ^2.2.3 + equatable: ^2.0.5 diff --git a/bin/server.dart b/bin/server.dart index 351b98d..d4eb661 100644 --- a/bin/server.dart +++ b/bin/server.dart @@ -10,7 +10,7 @@ import 'package:args/args.dart'; import 'database/database.dart'; import 'models/user.dart'; import 'models/playlist.dart'; -import 'package:xtremflow/core/models/playlist_config.dart'; +import '../lib/core/models/playlist_config.dart'; import 'api/auth_handler.dart'; import 'api/users_handler.dart'; import 'api/playlists_handler.dart'; @@ -153,12 +153,16 @@ void main(List args) async { return null; } + // Create Streaming Router (Mount handlers on correct paths) + final streamingRouter = Router() + ..mount('/api/live', createLiveStreamHandler(_getPlaylist)) + ..mount('/api/vod', createVodStreamHandler(_getPlaylist)); + // Main handler with API proxy and NEW Streaming Handlers final handler = Cascade() - .add(_createApiHandler(apiRouter)) + .add(apiRouter.call) /* Standard API endpoints */ .add(_createXtreamProxyHandler()) /* Keep for general API calls */ - .add(createLiveStreamHandler(_getPlaylist)) - .add(createVodStreamHandler(_getPlaylist)) + .add(streamingRouter.call) /* Streaming endpoints */ .add(staticHandler) .handler; @@ -190,22 +194,7 @@ void main(List args) async { }); } -/// Create API handler -Handler _createApiHandler(Router apiRouter) { - return (Request request) async { - final path = request.url.path; - - // Only handle /api/* requests (excluding special handlers) - if (path.startsWith('api/') && - !path.startsWith('api/xtream/') && - !path.startsWith('api/live/') && - !path.startsWith('api/vod/')) { - return apiRouter(request); - } - - return Response.notFound('Not found'); - }; -} + /// CORS middleware to allow cross-origin requests Middleware _corsMiddleware() { diff --git a/build_log.txt b/build_log.txt new file mode 100644 index 0000000000000000000000000000000000000000..1c0f614c147fb421435a4bcebca3f0469d68087e GIT binary patch literal 68014 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 QTzYsyFD7I74ot59e`rA;O#lD@ literal 0 HcmV?d00001 diff --git a/build_log_2.txt b/build_log_2.txt new file mode 100644 index 0000000000000000000000000000000000000000..7892e8f88fdf40025ace088d1af449099574e78d GIT binary patch literal 82154 zcmeI5>vG#jcE|B~tM(mO>q_j2N3t#7op`D|vOVj}#S?2h{$TB@bhAdWWGkY4ODcJ> zJV0I`50R%x^8ewmr@KLbY)~WtQYe*300bJ{r_cS;{eS=aI_qUuv$gDYc0)(USwH)W zzF%hVvh8dqJIeNTc9y-@=aD{lb@eR2wyisQ*&}`KWvBY(P~W|5BYT{EpRHzp%>Izk zGJjXqwr}~7?mpAqZ`9JRj(XWMwb9oRE$-%Rzt^w5>~i+w;BBY6e_QW=s`tFpoqhe* z)3v@n-{~5yoa)Jc$v)^RM|;`Vy4KI$>ik51hq~`TS3c-?Z_sMoOY1A2jK5AVztbDH z)he)hl^^rQeI2!_m+?$}r~bXuY%$9xg41s~6pN#77o6h}fHh#^X+DOd?Av_qk2DYM z9>uflx#0dpy*|jXa=+#MeJZ^EAV?dmUkTzn>i?c7t4-MbgZgzKT;9#TWb68VmwnV{ zU%cp0J%6EJkA>kMb9`x2zhmgO53a9r9NiP_J_(wOgSAMG-36nxA97fK$UZL+oPD34 zic9QDj`TH(?SUT9ZcglRWbyhQ^NkmR{X6|34NU`UH{`2(|5#(#(P$1djxXZbJK{V? z!l^d#>}TpzUm9{>y=ym|yPi&8+wWj{kzwjA&<*jZ9dUqtX_xKh0YB$Gg|A|hVy*MJ zD=ED{2fn&5ZDwC@!-6my{DG|N*V54+WScn;MP~JN{G)zHf7sUjM>>BK*&Ww%s~n37 zTYp7&nm^(|z6P^iKS^R7N^W4$p6Pvf0UqXF2IL1`4Ez@d`u?-@t4H!v&<;Kf{2nX% zJISBH()p4<`CjM8d20`{ztK1T4eoRPgNJ%wUu}9{$JOknJSpDS@kFDy9`EWtAm7Wb z>;H{fey_HHMcc>Z{UYWWSG$j*b?j3q#=H<^If`=Y92~PxX%)8%3*+Ol1l2~A; zrM4p`yVzQ4C@67(vAwaQiD8A>;8jII z?gy4RGeNcn(WH|+#$|bcv_}r@zJA}zf7wS@dI>SKM{4Ip zkuLhRt(e*mYMTsR;%gQc+|0A(=<~j=kp)U7F8Q;YdXgCDYTl=hI#2B%k)c(2BUTmr z*(^kV!c5@FA<Z#P;9lpKq%fXpSqU^vz&!Ti9^30D)9mNqGx$f*cE%t=kmOn53@;AvkA|o225% zi7@0$c!KOCyTVB;lb>yXOL`9t8s!pndKBaIinikkx{t??*;3F^PC?{gw;L+HpB^&9 zl#`}&jKWL*o~GcD);og&+Sf1?rb#hv(n`|!Y*~*DTF9e21$mUJous{+I-IaNuo+Ed zlD>viRn*{8W%h}r5OT+2t6RY_RgNdRPKIG~bd}OOviP7W`$QHOHMmqBlk&EvB~sdq zxn72_DN3bOI!b*b_D^#6~}0%N^C226Wn>$yH%$QPVU` zA-+?l$4$@U)D(rJ_)H82T~x!zpo$R~&pBsd`?Mq4Gs^afduY(;q8feKE|$^Z@uTQJ zO68|1bh?$>5AS3lE<;o!6*8mnvWsejk@I%>m(nnLw5O?yY7k+7&s14-Hzv+YN%I9a zrMIN@uIQm2_G6@asJo~JT6-~*F>My`odZ7 zj;%a9nc5C2Dp(<$OrX_4tcxu69koR@1~E)xd$v-Tt!mC1Lo2%fy*}M~V{uiZ(dyo>kEb_t-K{*H4Wzn5Ekkrqt_Y7@L|@Dy6=0x#BNr9J!kFH-{fx{H1zU%Ci%^ zteJ&=5_9eL;YHEY>h+Ye_)A)zc6GF)sqt6$XjJ?qoeL~m{Ds{W?#e&r)&PDg?{WD` zL$Tk!srik2;dP_o_)D69H*PPEb+luQai6M3>@}d#zRu!^+rhU+_bME9QS$?T)8@L` zkGVWijkKuaI7l>w`Q!TK@t})pK<}d|y&9TTD^Rs>-m7|Qn9!}2wKrJhrYfqD#t%|_ zC{5u;O5Y3{%Ay*nYbvC?r7hn3N&4zJXVLaa)&E9WTXD@sQ<#$8LxVV^aT7+S|OJyxmao{q&G2QckMIJqj=VdzykrTJH=BT~wpEg5)?)Q?aTf z6=%|@sV%nK_?0%xy-&7wV;9xvq8j1qW(Rdvo9uBs~Oq8ep&cgwj}Ru|R4wqOOYID*g=Z!dcI!}Ytoja7`} zr0dJ!YGXxhvn^we_4RPn#i#~xxzH04*O0K+hFioaMEB1S1T0$MJ-qpY+IH(6@2DT(tE+=L(YyayXVp*~ zKRd>8&O|vLvSE8M{)}(WXp#(Aw?hut>NT@by>*zvc%iAI{5hlRcs4f#1+dIlj>Wj} zZ`rd_{CT04w*@h%;QPTGuIdaZvrErejujq@*q!K?0i{B@NBOwSvkUcwPxf`r2%x|s zHqy>CFvHJL8aCE}0vJ6B4E%HRfPmr1C>opwoZVYeDe&JT8jNYiVKr21bg(OG0}H8E zgqp#Qi;B@+Hf{+P@HcqzFx(y2-&D2cw$_H;(Yh-)#J_Lpcw2wB^bDN*Mt;1fwPJV0 zpVxH0CV91^-*@TlfP)pG2IU(}s=Uv;Fbuu$~Ow0BqZXME_B2RcuQ8-&;Fb}(!D?F$shED+2lLwebqa@Q|rIz zT`%=Up1{|KuL!ICn*Q)KcyTYLRYVoH2?^nX&vHJBQhejFX zEnkD&+Ol4}(%Zky;kc3aV?*P5ruN3oaoKaP^xTFZ1a{#ewpE`-y>(qr{3HnS9Pb@9 zqo1UAeG(2G46p+(u&eX(xn0rqqWyhMSB7EwMwod=ci$C!@8w>L9rYid1arBjXYgn6 zN@knm7^T`iwgJQh*vDP!w8S#{cFG5IrU{X(mTvwXshgYdQrRa z5a`(odvLW-`#8<9lbtqg|M-VGAJ#*f&^k6njJ$HF7>w49G@d?w8LKu>e}gX!CN$ZqIATru9V((py#mp#k12qfJ#=?-XiA9X}# z%bs)&%S*U6z-sO{>+nDv(6SbsZ;aLM$ZH^n&C$t&+@p3!9ung34|3m~&xr_+o(N-! z@SP5PY*^Bl)t=?Gz00ZWvLJFk)k% z-J1XPuOr%+FYNIc0DEQteDHk?k7C$Ak0Du+9(YnvX8j|^WId3JT7 z?%s?h3+~{-0C&j~bF=TxXdRy%p1()BAFlmb+sPh`&2YSz4@eKXiDepP=CXTh(! zS;B`|WhLCrwVqD%Igh1fFzhs+Sy{4^z;_m$q^|sJk37AXYvqfn`49!D3;CjEGw!^7 zGqp^b&pc+ZO`4CRwmNe-3w~8k^SM~Fw3g@fbUq(swna|r`Q5r~$gder`s?9*uzOp$EorTS_4(Jm5hPMfwD6Z@cOd`t7A z=sHn`beOhBXPpk8oCZawL$6Kzur5Y6N5}2LIplI3D`_}JURO2~QBRT0UnwqD&0m~9 zVUclg7?$&;-^IqnX;ScF;o6P79tQod4&}Nvd@QrcJ4sf}q`a3F1w68uh7W$0u$yRFn zqVv-{Kh*ykj)$DYwvLCMvojExhK$H@O7dPU#ie=vH>5Q5&X>ephA{F-$xuNj;sSKX?f=oPJUjjYg9agq0fYv1U)f8JIV zBnO$bjL-5}f=<54{#LW#-v1w2Gk+n!0}ktg8kz>#g24NkAcp2poEy%8;7|JPO!|Xm z%el;Mz1*!kZ?%5KaXl4YP*eLQ`zIaQ z3Z0fExu>UHKKHX+n%KBZj<}59W4#NzDZJa>!KcIBcrE*%bG%?}Pof1j0?QGH7JB(r zSo`z0gH0bDP}vZSfc69P*s&NH%A&nY@Ae(f3TJwdxWy8mu$pD!z`(%OG@r zGG@_!kff|~i%#rpLaR~bH{QurcpyD5t{mc?T`fpV^o#wx8po}GYi%D(KGLSi6l5}- zka1JD!z$8zn~dju)zGq4kWJ!Rb((u_C5Ks9NoH_CH|PhDp$Y`JF;1Rk4H$#5s|+dU zC0RJpo2oGt4C;Jk4c}Nv+U+ad+El zJHVY>=TW}>`B|}OmR7^lRZ$tW&lmPx6_w|))kkgdLE{hXs;F2^dh(1K2gCEm*6T(^ z>cls}#6^v{PX^y<`uZImFERwXDk?XNW#4V$$Mq|4(DBUw;WfC~R%BvlVmY*@4z4|s zN%&R$Ih+N*>Sn2{qGJ6*EWz2VS20PI&-}U7;>ztw;5!RWvbYd*bsdXXKR%D@j`nCi zZl>yFsLY?2)RU?6n87w_K9kJhEcjJ7OVyf>t5E6c$0zssI2d+5pV?@ZlficuoMcfo zpXpQw)b&YrRaAJFd_D)UwqYG*8adm%=OW?ev}yZd)T|8SUR{c=6JF~*E zP;@%<+G4Xg*wv})YmScFg>zjM)pXX(odgGmx#E23cd;>XniSksQ5Dzp?W(Azxu!PI zB%`mZq$-PgyKBQ$R9pdW?vD67wr|!I3r?$~idzZKtPPjpj@2}Nz52Lf!tV)4?ZxzV z4g?BiyY?*R?twO%s-1kA+Ck9us<;cvV(lVWHHxGf^sTzUXk)?b$mvAqbaV;#v zo-Q`V`R^*od&hIdcJ2i;ytAN#Vq96#=G_Gs8UDk2!!Vjq0{i1js@(Nw)VY07t{2sA z)O{Q&=Zh*r+hhJyN#z@L>+!4>_c^1^_`UwvgOnHyJ8WK4&4JZ4QW+aoF!;(*a{Dd6 z{PxJ&;!Ch}01+{6+s{B_3;r+408Ju`u&ie-q9x*1UN}rVpF)+L};%b@fhGF|nCfzi`d>&{r&3 zEsv|^U)4QSI9<_fnKtaIjos=1y?n2tuaz0tAI!V!kDnPTB>z;XYjV}Uf6{M8HE(sq zY6SnC{a5y%Is%`lfF8AW!zJD4-_uhq@VCFu^Rpa_m>Y0yU+rw=RY`6?YJO)1saB$H zb#nTy!V8acF~)efvv%11d@X``Qq8RhW>oOH{hw@SEh?r~Gbk0>d?#F|j?HM4^$DoQ zw){IPvag7yjP4%j8_EFQtR)h*>+iX(Jug_JiaMt0Q$vUi{`it$?9ayG3AEv`B;+DZ zVaQEkIeUe$_H?y;n=WU)6T$0Z;0UXr_`lJ-q{ER*;$0qEz3izt0~BvO)$`$vKvvFH z4yW+jI|EJ2_OO{3HQkRO^-5A_Cy-Rgpb#?l`=s2)RsTAPZL9u-GUtB2>kupO&ySyw zQRK13V~343_LDh%HNHA2JPZ!b2Zw$Z;)y{kgwC2IGV*D(EulFl=gwVs1xh)7H-|x;9zd~E!k*tW5e2p&C@mRrUUXb(l z9+(%t-|Ij?iOlW!T1z(~Z8^p(vxaTH9i-wr%IMGR9%zcOdW_f-)?i(`_Wa1v`fM$$ zn{&mEQ0E;*U*qABPI*X|$!yIKdT7$4sIMBOLQ}xVj0DN|~f{#gS zTP2iLZY++0e~>7%TS=(eE9l?tVQT9NR$Ej>|GW3K|03N1uQ~Zk_@3&{!my{^X(Q-g z;e6PxW1}^XqLLGmO71w!59QA| zeKDkmrmVG48}DgX_s&`i`6$Olk9BN|y@;$UoBjBXG9J1p)>^0?7yXLyD96Jgo$@ZC zwH9j99UT^F(CBcKm%A=DmQm$$TWg_~-5Yp?QfV^vzPeBirDZG)o3YkH&v+*bhp7;a zJj{GqRBNr;YI1Uns3I%VGTOfKW3Ve(8TON|_jHb(^fr$HyDW>V^1pb?Z=>=V@@sbW gbaBOa+F^BVi_bU<61x^l%=O3b@jx4HWmLxV|M?Q`7XSbN literal 0 HcmV?d00001 diff --git a/lib/features/iptv/providers/settings_provider.dart b/lib/features/iptv/providers/settings_provider.dart index eb3733b..d055984 100644 --- a/lib/features/iptv/providers/settings_provider.dart +++ b/lib/features/iptv/providers/settings_provider.dart @@ -299,7 +299,6 @@ class IptvSettingsNotifier extends StateNotifier { preferredAspectRatio: getValue(_SettingsKeys.preferredAspectRatio), playerType: remoteSettings[_SettingsKeys.playerType] != null ? PlayerType.values[remoteSettings[_SettingsKeys.playerType] as int] : null, - forceVodTranscoding: getValue(_SettingsKeys.forceVodTranscoding), ); } _initialized = true; diff --git a/lib/features/iptv/widgets/streaming_settings_tab.dart b/lib/features/iptv/widgets/streaming_settings_tab.dart index 8b2c53c..0d4eaf4 100644 --- a/lib/features/iptv/widgets/streaming_settings_tab.dart +++ b/lib/features/iptv/widgets/streaming_settings_tab.dart @@ -150,20 +150,7 @@ class StreamingSettingsTab extends ConsumerWidget { activeColor: Colors.blueAccent, onChanged: (v) => notifier.setPreferDirectPlay(v), ), - Divider(height: 1, color: Colors.white.withOpacity(0.1)), - SwitchListTile( - title: Text( - 'Forcer audio VOD (Films/Séries)', - style: GoogleFonts.roboto(fontSize: 14, color: Colors.white), - ), - subtitle: Text( - 'Active FFmpeg pour garantir le son\n⚠️ Désactive le seeking', - style: GoogleFonts.roboto(fontSize: 12, color: Colors.white54), - ), - value: settings.forceVodTranscoding, - activeColor: Colors.orangeAccent, - onChanged: (v) => notifier.setForceVodTranscoding(v), - ), + ], ), const SizedBox(height: 16),