Skip to content

Commit 64a58ed

Browse files
committed
New Functionality: Remote Video URLs
1 parent e9832f0 commit 64a58ed

File tree

11 files changed

+210
-60
lines changed

11 files changed

+210
-60
lines changed

README.md

+21-41
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,38 @@
33
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FThe-Igor%2Fswiftui-loop-videoplayer%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/The-Igor/swiftui-loop-videoplayer)
44
[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FThe-Igor%2Fswiftui-loop-videoplayer%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/The-Igor/swiftui-loop-videoplayer)
55

6-
## How to use the package
7-
### 1. Create LoopPlayerView
8-
9-
```swift
10-
LoopPlayerView(fileName: "swipe")
11-
```
12-
13-
or in a declarative way
14-
15-
```swift
16-
LoopPlayerView{
17-
Settings{
18-
FileName("swipe")
19-
Ext("mp4")
20-
Gravity(.resizeAspectFill)
21-
ErrorGroup{
22-
EColor(.accentColor)
23-
EFontSize(27)
24-
}
25-
}
26-
}
27-
```
28-
29-
```swift
30-
LoopPlayerView{
31-
Settings{
32-
FileName("swipe")
33-
Ext("mp4")
34-
Gravity(.resizeAspectFill)
35-
EFontSize(27)
36-
}
37-
}
38-
```
39-
You can group error settings in group **ErrorGroup** or just pass all settings as a linear list of settings. You don't need to follow some specific order for settings, just pass in an arbitrary oder you are interested in. The only required setting is **FileName**.
406
![The concept](https://github.com/The-Igor/swiftui-loop-videoplayer-example/blob/main/swiftui-loop-videoplayer-example/img/swiftui.gif)
417
![The concept](https://github.com/The-Igor/swiftui-loop-videoplayer-example/blob/main/swiftui-loop-videoplayer-example/img/macos.gif)
428

439

44-
4510
### Settings
4611

4712
| Name | Description | Default |
48-
| --- | --- | --- |
49-
|**FileName("swipe")**| Name of the video to play| - |
50-
|**Ext("mp4")**| Video extension | "mp4" |
51-
|**Gravity(.resizeAspectFill)**| A structure that defines how a layer displays a player’s visual content within the layer’s bounds | .resizeAspect |
52-
|**EColor(.accentColor)**| Error message text color| .red |
53-
|**EFontSize(27)**| Size of the error text | 17.0 |
13+
| --- | --- | --- |
14+
| **SourceName** | The URL or local filename of the video. If a valid URL (http or https) is provided, the video will be streamed from the URL. If not a URL, the system will check if a video with the given name exists in the local bundle. The local name provided can either include an extension or be without one. The system first checks if the local name contains an extension. If the local name includes an extension, it extracts this extension and uses it as the default. If the local name does not contain an extension, the system assigns a default extension of .mp4 The default file extension can be set up via Ext param. | - |
15+
| **Ext** | File extension for the video, used when loading from local resources. This is optional when a URL is provided and the URL ends with the video file extension. | "mp4" |
16+
| **Gravity** | How the video content should be resized to fit the player's bounds. | .resizeAspect |
17+
| **EColor** | Error message text color. | .red |
18+
| **EFontSize** | Size of the error text. | 17.0 |
5419

5520
### Change video file dynamically
5621
![The concept](https://github.com/The-Igor/swiftui-loop-videoplayer-example/blob/main/swiftui-loop-videoplayer-example/img/change_video_file.gif)
5722

23+
## New Functionality: Remote Video URLs
24+
25+
### Video Source Compatibility
26+
27+
| Video Source | Possible to Use | Comments |
28+
| --- | --- | --- |
29+
| YouTube | No | Violates YouTube's policy as it doesn't allow direct video streaming outside its platform. |
30+
| Direct MP4 URLs | Yes | Directly accessible MP4 URLs can be used if they are hosted on servers that permit CORS. |
31+
| HLS Streams | Yes | HLS streams are supported and can be used for live streaming purposes. |
32+
33+
## Disclaimer on Video Sources
34+
Please note that using videos from URLs requires ensuring that you have the right to use and stream these videos. Videos hosted on platforms like YouTube cannot be used directly due to restrictions in their terms of service. Always ensure the video URL is compliant with copyright laws and platform policies.
35+
36+
![The concept](https://github.com/The-Igor/swiftui-loop-videoplayer-example/blob/main/swiftui-loop-videoplayer-example/img/remote_video_player_swiftui.gif)
37+
5838
## Practical idea for the package
5939
You can introduce video hints about some functionality into the app, for example how to add positions to favorites. Put loop video hint into background or open as popup.
6040

swiftui-loop-videoplayer-example.xcodeproj/project.pbxproj

+23-8
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
784A16232A58374B00E8BBEA /* swiftui.gif in Resources */ = {isa = PBXBuildFile; fileRef = 784A16222A58374B00E8BBEA /* swiftui.gif */; };
1212
786A7B892C5CB80200018844 /* logo.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 786A7B882C5CB80200018844 /* logo.mp4 */; };
1313
786A7B8C2C5CBA4D00018844 /* swiftui-loop-videoplayer in Frameworks */ = {isa = PBXBuildFile; productRef = 786A7B8B2C5CBA4D00018844 /* swiftui-loop-videoplayer */; };
14-
786A7B912C5CCC8100018844 /* swiftui-loop-videoplayer in Frameworks */ = {isa = PBXBuildFile; productRef = 786A7B902C5CCC8100018844 /* swiftui-loop-videoplayer */; };
1514
786A7B932C5CCC8800018844 /* change_video_file.gif in Resources */ = {isa = PBXBuildFile; fileRef = 786A7B922C5CCC8800018844 /* change_video_file.gif */; };
15+
786A7B992C60B87E00018844 /* swiftui-loop-videoplayer in Frameworks */ = {isa = PBXBuildFile; productRef = 786A7B982C60B87E00018844 /* swiftui-loop-videoplayer */; };
16+
786A7B9C2C61382C00018844 /* remote_video_player_swiftui.gif in Resources */ = {isa = PBXBuildFile; fileRef = 786A7B9B2C61382C00018844 /* remote_video_player_swiftui.gif */; };
17+
786A7B9F2C6138AE00018844 /* swiftui-loop-videoplayer in Frameworks */ = {isa = PBXBuildFile; productRef = 786A7B9E2C6138AE00018844 /* swiftui-loop-videoplayer */; };
1618
788D66212A5B1B7B0047A134 /* swiftui_video_hint.gif in Resources */ = {isa = PBXBuildFile; fileRef = 788D66202A5B1B7B0047A134 /* swiftui_video_hint.gif */; };
1719
78AF7BEC2A52A9DA0028E9E3 /* swiftui_loop_videoplayer_exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78AF7BEB2A52A9DA0028E9E3 /* swiftui_loop_videoplayer_exampleApp.swift */; };
1820
78AF7BEE2A52A9DA0028E9E3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78AF7BED2A52A9DA0028E9E3 /* ContentView.swift */; };
@@ -28,6 +30,8 @@
2830
784A16222A58374B00E8BBEA /* swiftui.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = swiftui.gif; sourceTree = "<group>"; };
2931
786A7B882C5CB80200018844 /* logo.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = logo.mp4; sourceTree = "<group>"; };
3032
786A7B922C5CCC8800018844 /* change_video_file.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = change_video_file.gif; sourceTree = "<group>"; };
33+
786A7B9A2C60C77800018844 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
34+
786A7B9B2C61382C00018844 /* remote_video_player_swiftui.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = remote_video_player_swiftui.gif; sourceTree = "<group>"; };
3135
788D66202A5B1B7B0047A134 /* swiftui_video_hint.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = swiftui_video_hint.gif; sourceTree = "<group>"; };
3236
78AF7BE82A52A9DA0028E9E3 /* swiftui-loop-videoplayer-example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "swiftui-loop-videoplayer-example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
3337
78AF7BEB2A52A9DA0028E9E3 /* swiftui_loop_videoplayer_exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = swiftui_loop_videoplayer_exampleApp.swift; sourceTree = "<group>"; };
@@ -44,8 +48,9 @@
4448
isa = PBXFrameworksBuildPhase;
4549
buildActionMask = 2147483647;
4650
files = (
51+
786A7B9F2C6138AE00018844 /* swiftui-loop-videoplayer in Frameworks */,
4752
786A7B8C2C5CBA4D00018844 /* swiftui-loop-videoplayer in Frameworks */,
48-
786A7B912C5CCC8100018844 /* swiftui-loop-videoplayer in Frameworks */,
53+
786A7B992C60B87E00018844 /* swiftui-loop-videoplayer in Frameworks */,
4954
);
5055
runOnlyForDeploymentPostprocessing = 0;
5156
};
@@ -73,6 +78,7 @@
7378
78AF7BEA2A52A9DA0028E9E3 /* swiftui-loop-videoplayer-example */ = {
7479
isa = PBXGroup;
7580
children = (
81+
786A7B9A2C60C77800018844 /* Info.plist */,
7682
78AF7C012A52BDDF0028E9E3 /* img */,
7783
78AF7BFB2A52AA5D0028E9E3 /* Resources */,
7884
78AF7BEB2A52A9DA0028E9E3 /* swiftui_loop_videoplayer_exampleApp.swift */,
@@ -110,6 +116,7 @@
110116
78AF7C012A52BDDF0028E9E3 /* img */ = {
111117
isa = PBXGroup;
112118
children = (
119+
786A7B9B2C61382C00018844 /* remote_video_player_swiftui.gif */,
113120
786A7B922C5CCC8800018844 /* change_video_file.gif */,
114121
7810A3D42A7CE3570032340D /* tip_video_swiftui.gif */,
115122
78B42EF22C529785005E2367 /* macos.gif */,
@@ -137,7 +144,8 @@
137144
name = "swiftui-loop-videoplayer-example";
138145
packageProductDependencies = (
139146
786A7B8B2C5CBA4D00018844 /* swiftui-loop-videoplayer */,
140-
786A7B902C5CCC8100018844 /* swiftui-loop-videoplayer */,
147+
786A7B982C60B87E00018844 /* swiftui-loop-videoplayer */,
148+
786A7B9E2C6138AE00018844 /* swiftui-loop-videoplayer */,
141149
);
142150
productName = "swiftui-loop-videoplayer-example";
143151
productReference = 78AF7BE82A52A9DA0028E9E3 /* swiftui-loop-videoplayer-example.app */;
@@ -168,7 +176,7 @@
168176
);
169177
mainGroup = 78AF7BDF2A52A9DA0028E9E3;
170178
packageReferences = (
171-
786A7B8F2C5CCC8100018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */,
179+
786A7B9D2C6138AE00018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */,
172180
);
173181
productRefGroup = 78AF7BE92A52A9DA0028E9E3 /* Products */;
174182
projectDirPath = "";
@@ -188,6 +196,7 @@
188196
78B42EF32C529785005E2367 /* macos.gif in Resources */,
189197
78AF7BF32A52A9DB0028E9E3 /* Preview Assets.xcassets in Resources */,
190198
78AF7BFD2A52AA5D0028E9E3 /* swipe.mp4 in Resources */,
199+
786A7B9C2C61382C00018844 /* remote_video_player_swiftui.gif in Resources */,
191200
78AF7C072A52BFBB0028E9E3 /* README.md in Resources */,
192201
7810A3D52A7CE3570032340D /* tip_video_swiftui.gif in Resources */,
193202
784A16232A58374B00E8BBEA /* swiftui.gif in Resources */,
@@ -337,6 +346,7 @@
337346
DEVELOPMENT_TEAM = FZ42RW4USG;
338347
ENABLE_PREVIEWS = YES;
339348
GENERATE_INFOPLIST_FILE = YES;
349+
INFOPLIST_FILE = "swiftui-loop-videoplayer-example/Info.plist";
340350
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
341351
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
342352
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -365,6 +375,7 @@
365375
DEVELOPMENT_TEAM = FZ42RW4USG;
366376
ENABLE_PREVIEWS = YES;
367377
GENERATE_INFOPLIST_FILE = YES;
378+
INFOPLIST_FILE = "swiftui-loop-videoplayer-example/Info.plist";
368379
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
369380
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
370381
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -406,9 +417,9 @@
406417
/* End XCConfigurationList section */
407418

408419
/* Begin XCRemoteSwiftPackageReference section */
409-
786A7B8F2C5CCC8100018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */ = {
420+
786A7B9D2C6138AE00018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */ = {
410421
isa = XCRemoteSwiftPackageReference;
411-
repositoryURL = "https://github.com/The-Igor/swiftui-loop-videoplayer";
422+
repositoryURL = "https://github.com/The-Igor/swiftui-loop-videoplayer.git";
412423
requirement = {
413424
branch = main;
414425
kind = branch;
@@ -421,9 +432,13 @@
421432
isa = XCSwiftPackageProductDependency;
422433
productName = "swiftui-loop-videoplayer";
423434
};
424-
786A7B902C5CCC8100018844 /* swiftui-loop-videoplayer */ = {
435+
786A7B982C60B87E00018844 /* swiftui-loop-videoplayer */ = {
425436
isa = XCSwiftPackageProductDependency;
426-
package = 786A7B8F2C5CCC8100018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */;
437+
productName = "swiftui-loop-videoplayer";
438+
};
439+
786A7B9E2C6138AE00018844 /* swiftui-loop-videoplayer */ = {
440+
isa = XCSwiftPackageProductDependency;
441+
package = 786A7B9D2C6138AE00018844 /* XCRemoteSwiftPackageReference "swiftui-loop-videoplayer" */;
427442
productName = "swiftui-loop-videoplayer";
428443
};
429444
/* End XCSwiftPackageProductDependency section */

swiftui-loop-videoplayer-example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
2-
"originHash" : "c8f8740e5fb77b346e17e8f6f27e0c5aad90741b9d780ddb2bd217c28ec8b488",
2+
"originHash" : "4a6c5f86155d1e838f9840fc9be719bd3dfed1ed467b16e89e68b5a0091ca397",
33
"pins" : [
44
{
55
"identity" : "swiftui-loop-videoplayer",
66
"kind" : "remoteSourceControl",
7-
"location" : "https://github.com/The-Igor/swiftui-loop-videoplayer",
7+
"location" : "https://github.com/The-Igor/swiftui-loop-videoplayer.git",
88
"state" : {
99
"branch" : "main",
10-
"revision" : "0e31b4ccf26918f9bec4f8b3362800acf23b743e"
10+
"revision" : "cbb63a3e747a81b525afbff4fd0cf9ad4186a90b"
1111
}
1212
}
1313
],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<array/>
5+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1540"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES"
8+
buildArchitectures = "Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting = "YES"
12+
buildForRunning = "YES"
13+
buildForProfiling = "YES"
14+
buildForArchiving = "YES"
15+
buildForAnalyzing = "YES">
16+
<BuildableReference
17+
BuildableIdentifier = "primary"
18+
BlueprintIdentifier = "78AF7BE72A52A9DA0028E9E3"
19+
BuildableName = "swiftui-loop-videoplayer-example.app"
20+
BlueprintName = "swiftui-loop-videoplayer-example"
21+
ReferencedContainer = "container:swiftui-loop-videoplayer-example.xcodeproj">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
25+
</BuildAction>
26+
<TestAction
27+
buildConfiguration = "Debug"
28+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
29+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Debug"
35+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37+
launchStyle = "0"
38+
useCustomWorkingDirectory = "NO"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
debugServiceExtension = "internal"
42+
allowLocationSimulation = "YES">
43+
<BuildableProductRunnable
44+
runnableDebuggingMode = "0">
45+
<BuildableReference
46+
BuildableIdentifier = "primary"
47+
BlueprintIdentifier = "78AF7BE72A52A9DA0028E9E3"
48+
BuildableName = "swiftui-loop-videoplayer-example.app"
49+
BlueprintName = "swiftui-loop-videoplayer-example"
50+
ReferencedContainer = "container:swiftui-loop-videoplayer-example.xcodeproj">
51+
</BuildableReference>
52+
</BuildableProductRunnable>
53+
</LaunchAction>
54+
<ProfileAction
55+
buildConfiguration = "Release"
56+
shouldUseLaunchSchemeArgsEnv = "YES"
57+
savedToolIdentifier = ""
58+
useCustomWorkingDirectory = "NO"
59+
debugDocumentVersioning = "YES">
60+
<BuildableProductRunnable
61+
runnableDebuggingMode = "0">
62+
<BuildableReference
63+
BuildableIdentifier = "primary"
64+
BlueprintIdentifier = "78AF7BE72A52A9DA0028E9E3"
65+
BuildableName = "swiftui-loop-videoplayer-example.app"
66+
BlueprintName = "swiftui-loop-videoplayer-example"
67+
ReferencedContainer = "container:swiftui-loop-videoplayer-example.xcodeproj">
68+
</BuildableReference>
69+
</BuildableProductRunnable>
70+
</ProfileAction>
71+
<AnalyzeAction
72+
buildConfiguration = "Debug">
73+
</AnalyzeAction>
74+
<ArchiveAction
75+
buildConfiguration = "Release"
76+
revealArchiveInOrganizer = "YES">
77+
</ArchiveAction>
78+
</Scheme>

swiftui-loop-videoplayer-example.xcodeproj/xcuserdata/igor.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
endingColumnNumber = "9223372036854775807"
1717
startingLineNumber = "79"
1818
endingLineNumber = "79"
19-
landmarkName = "makeUIView(context:)"
20-
landmarkType = "7">
19+
landmarkName = "LoopPlayerViewRepresentableIOS"
20+
landmarkType = "14">
2121
</BreakpointContent>
2222
</BreakpointProxy>
2323
</Breakpoints>

swiftui-loop-videoplayer-example.xcodeproj/xcuserdata/igor.xcuserdatad/xcschemes/xcschememanagement.plist

+8
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,13 @@
1010
<integer>0</integer>
1111
</dict>
1212
</dict>
13+
<key>SuppressBuildableAutocreation</key>
14+
<dict>
15+
<key>78AF7BE72A52A9DA0028E9E3</key>
16+
<dict>
17+
<key>primary</key>
18+
<true/>
19+
</dict>
20+
</dict>
1321
</dict>
1422
</plist>

0 commit comments

Comments
 (0)